Commit bee3a686 authored by Krasimir Angelov's avatar Krasimir Angelov

Extract JWT encoding/decoding for Conan packages

Move handling of JWT for Conan packages into Gitlab::ConanToken.
parent 886b06a3
# frozen_string_literal: true
module API
class ConanPackages < Grape::API
HMAC_KEY = 'gitlab-conan-packages'.freeze
helpers ::API::Helpers::PackagesHelpers
before do
......@@ -21,12 +20,7 @@ module API
detail 'This feature was introduced in GitLab 12.2'
end
get 'authenticate' do
jwt = JSONWebToken::HMACToken.new(jwt_secret)
jwt['pat'] = access_token.id
jwt['u'] = access_token.user_id
jwt.expire_time = jwt.issued_at + 1.hour
jwt.encoded
::Gitlab::ConanToken.from_personal_access_token(access_token)
end
end
......@@ -56,9 +50,9 @@ module API
jwt = Doorkeeper::OAuth::Token.from_bearer_authorization(current_request)
return unless jwt
payload = JSONWebToken::HMACToken.decode(jwt, jwt_secret).first
token = ::Gitlab::ConanToken.decode(jwt)
PersonalAccessToken.find_by_id_and_user_id(payload['pat'], payload['u'])
PersonalAccessToken.find_by_id_and_user_id(token.personal_access_token_id, token.user_id)
rescue JWT::DecodeError
unauthorized!
end
......@@ -70,14 +64,6 @@ module API
PersonalAccessToken.find_by_token(token)
end
def jwt_secret
OpenSSL::HMAC.hexdigest(
OpenSSL::Digest::SHA256.new,
::Settings.attr_encrypted_db_key_base,
HMAC_KEY
)
end
end
end
end
# frozen_string_literal: true
module Gitlab
class ConanToken
HMAC_KEY = 'gitlab-conan-packages'.freeze
attr_reader :personal_access_token_id, :user_id
class << self
def from_personal_access_token(personal_access_token)
new(personal_access_token_id: personal_access_token.id, user_id: personal_access_token.user_id)
end
def decode(jwt)
payload = JSONWebToken::HMACToken.decode(jwt, secret).first
new(personal_access_token_id: payload['pat'], user_id: payload['u'])
end
def secret
OpenSSL::HMAC.hexdigest(
OpenSSL::Digest::SHA256.new,
::Settings.attr_encrypted_db_key_base,
HMAC_KEY
)
end
end
def initialize(personal_access_token_id:, user_id:)
@personal_access_token_id = personal_access_token_id
@user_id = user_id
end
def to_s
hmac_token.encoded
end
private
def hmac_token
JSONWebToken::HMACToken.new(self.class.secret).tap do |token|
token['pat'] = personal_access_token_id
token['u'] = user_id
token.expire_time = token.issued_at + 1.hour
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::ConanToken do
let(:base_secret) { SecureRandom.base64(64) }
let(:jwt_secret) do
OpenSSL::HMAC.hexdigest(
OpenSSL::Digest::SHA256.new,
base_secret,
described_class::HMAC_KEY
)
end
before do
allow(Settings).to receive(:attr_encrypted_db_key_base).and_return(base_secret)
end
def build_jwt(personal_access_token_id:, user_id:)
JSONWebToken::HMACToken.new(jwt_secret).tap do |jwt|
jwt['pat'] = personal_access_token_id
jwt['u'] = user_id || user_id
jwt.expire_time = jwt.issued_at + 1.hour
end
end
describe '.from_personal_access_token' do
it 'sets personal access token id and user id' do
personal_access_token = double(id: 123, user_id: 456)
token = described_class.from_personal_access_token(personal_access_token)
expect(token.personal_access_token_id).to eq(123)
expect(token.user_id).to eq(456)
end
end
describe '.decode' do
it 'sets personal access token id and user id' do
jwt = build_jwt(personal_access_token_id: 123, user_id: 456)
token = described_class.decode(jwt.encoded)
expect(token.personal_access_token_id).to eq(123)
expect(token.user_id).to eq(456)
end
end
describe '#to_s' do
it 'returns the encoded JWT' do
allow(SecureRandom).to receive(:uuid).and_return('u-u-i-d')
Timecop.freeze do
jwt = build_jwt(personal_access_token_id: 123, user_id: 456)
token = described_class.new(personal_access_token_id: 123, user_id: 456)
expect(token.to_s).to eq(jwt.encoded)
end
end
end
end
......@@ -2,13 +2,13 @@
require 'spec_helper'
describe API::ConanPackages do
let(:base_secret) { SecureRandom.base64(32) }
let(:base_secret) { SecureRandom.base64(64) }
let(:jwt_secret) do
OpenSSL::HMAC.hexdigest(
OpenSSL::Digest::SHA256.new,
base_secret,
API::ConanPackages::HMAC_KEY
Gitlab::ConanToken::HMAC_KEY
)
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment