Class: Authn::Tokens::Jwt

Inherits:
Object
  • Object
show all
Includes:
Gitlab::Utils::StrongMemoize
Defined in:
lib/authn/tokens/jwt.rb

Constant Summary collapse

InvalidSubjectForTokenError =
Class.new(StandardError)
ISSUER =
Settings.gitlab.host
AUDIENCE =
'gitlab-authz-token'
VERSION =
'0.1.0'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(payload:, subject_type:) ⇒ Jwt

Returns a new instance of Jwt.



66
67
68
69
# File 'lib/authn/tokens/jwt.rb', line 66

def initialize(payload:, subject_type:)
  @payload = payload
  @subject_type = subject_type
end

Instance Attribute Details

#payloadObject (readonly)

Returns the value of attribute payload.



81
82
83
# File 'lib/authn/tokens/jwt.rb', line 81

def payload
  @payload
end

#subject_typeObject (readonly)

Returns the value of attribute subject_type.



81
82
83
# File 'lib/authn/tokens/jwt.rb', line 81

def subject_type
  @subject_type
end

Class Method Details

.rsa_decode(token:, signing_public_key:, subject_type:, token_prefix:) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/authn/tokens/jwt.rb', line 52

def rsa_decode(token:, signing_public_key:, subject_type:, token_prefix:)
  return unless token.start_with?(token_prefix)

  token = token.delete_prefix(token_prefix)

  payload, _header = ::JSONWebToken::RSAToken.decode(token, signing_public_key)

  new(payload: payload, subject_type: subject_type)
rescue JWT::DecodeError
  # The token received is not a JWT
  nil
end

.rsa_encode(subject:, signing_key:, expire_time:, token_prefix:, custom_payload: {}) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/authn/tokens/jwt.rb', line 29

def rsa_encode(subject:, signing_key:, expire_time:, token_prefix:, custom_payload: {})
  subject_global_id = GlobalID.create(subject).to_s if subject
  raise InvalidSubjectForTokenError unless subject_global_id.present?

  jwt = ::JSONWebToken::Token.new.tap do |token|
    token.subject = subject_global_id
    token.issuer = ISSUER
    token.audience = AUDIENCE
    token.expire_time = expire_time
    token[:version] = VERSION

    custom_payload.each { |key, value| token[key] = value } if custom_payload.present?
  end

  token = ::JSONWebToken::RSAToken.encode(
    jwt.payload,
    signing_key,
    signing_key.public_key.to_jwk[:kid]
  )

  token_prefix + token
end

Instance Method Details

#subjectObject



71
72
73
74
75
76
77
78
# File 'lib/authn/tokens/jwt.rb', line 71

def subject
  return unless payload

  GitlabSchema.parse_gid(payload['sub'], expected_type: subject_type)&.find
rescue Gitlab::Graphql::Errors::ArgumentError, ActiveRecord::RecordNotFound
  # The subject doesn't exist anymore
  nil
end