Class: OmniAuth::Auth0::JWTValidator

Inherits:
Object
  • Object
show all
Defined in:
lib/omniauth/auth0/jwt_validator.rb

Overview

JWT Validator class

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options, authorize_params = {}) ⇒ JWTValidator

Initializer

Parameters:

  • options

    object options.domain - Application domain. options.issuer - Application issuer (optional). options.client_id - Application Client ID. options.client_secret - Application Client Secret.



20
21
22
23
24
25
26
27
28
29
# File 'lib/omniauth/auth0/jwt_validator.rb', line 20

def initialize(options, authorize_params = {})
  @domain = uri_string(options.domain)

  # Use custom issuer if provided, otherwise use domain
  @issuer = @domain
  @issuer = uri_string(options.issuer) if options.respond_to?(:issuer)

  @client_id = options.client_id
  @client_secret = options.client_secret
end

Instance Attribute Details

#domainObject

Returns the value of attribute domain.



11
12
13
# File 'lib/omniauth/auth0/jwt_validator.rb', line 11

def domain
  @domain
end

#issuerObject

Returns the value of attribute issuer.



11
12
13
# File 'lib/omniauth/auth0/jwt_validator.rb', line 11

def issuer
  @issuer
end

Instance Method Details

#jwks_key(key, kid) ⇒ Object

Return a specific key from a JWKS object.

Parameters:

  • key

    string - Key to find in the JWKS.

  • kid

    string - Key ID to identify the right JWK.

Returns:

  • nil|string



95
96
97
98
99
100
# File 'lib/omniauth/auth0/jwt_validator.rb', line 95

def jwks_key(key, kid)
  return nil if blank?(jwks[:keys])

  matching_jwk = jwks[:keys].find { |jwk| jwk[:kid] == kid }
  matching_jwk[key] if matching_jwk
end

#jwks_public_cert(x5c) ⇒ Object

Get the JWKS from the issuer and return a public key.

Parameters:

  • x5c

    string - X.509 certificate chain from a JWKS.

Returns:

  • key - The X.509 certificate public key.



84
85
86
87
88
89
# File 'lib/omniauth/auth0/jwt_validator.rb', line 84

def jwks_public_cert(x5c)
  x5c = Base64.decode64(x5c)

  # https://docs.ruby-lang.org/en/2.4.0/OpenSSL/X509/Certificate.html
  OpenSSL::X509::Certificate.new(x5c).public_key
end

#token_head(jwt) ⇒ Object

Get the decoded head segment from a JWT.

Returns:

  • hash - The parsed head of the JWT passed, empty hash if not.



74
75
76
77
78
79
# File 'lib/omniauth/auth0/jwt_validator.rb', line 74

def token_head(jwt)
  jwt_parts = jwt.split('.')
  return {} if blank?(jwt_parts) || blank?(jwt_parts[0])

  json_parse(Base64.decode64(jwt_parts[0]))
end

#verify(jwt, authorize_params = {}) ⇒ Object

Verify a JWT.

Parameters:

  • jwt

    string - JWT to verify.

  • authorize_params (defaults to: {})

    hash - Authorization params to verify on the JWT

Returns:

  • hash - The verified token, if there were no exceptions.



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/omniauth/auth0/jwt_validator.rb', line 55

def verify(jwt, authorize_params = {})
  if !jwt
    raise OmniAuth::Auth0::TokenValidationError.new('ID token is required but missing')
  end

  parts = jwt.split('.')
  if parts.length != 3
    raise OmniAuth::Auth0::TokenValidationError.new('ID token could not be decoded')
  end

  key, alg = verify_signature(jwt)
  id_token, header = JWT.decode(jwt, key, false)
  verify_claims(id_token, authorize_params)

  return id_token
end

#verify_signature(jwt) ⇒ Object

Verify a token’s signature. Only tokens signed with the RS256 or HS256 signatures are supported.

Returns:

  • array - The token’s key and signing algorithm



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/omniauth/auth0/jwt_validator.rb', line 33

def verify_signature(jwt)
  head = token_head(jwt)

  # Make sure the algorithm is supported and get the decode key.
  if head[:alg] == 'RS256'
    key, alg = [rs256_decode_key(head[:kid]), head[:alg]]
  elsif head[:alg] == 'HS256'
    key, alg = [@client_secret, head[:alg]]
  else
    raise OmniAuth::Auth0::TokenValidationError.new("Signature algorithm of #{head[:alg]} is not supported. Expected the ID token to be signed with RS256 or HS256")
  end

  # Call decode to verify the signature
  JWT.decode(jwt, key, true, decode_opts(alg))

  return key, alg
end