class JWT::Decode

The Decode class is responsible for decoding and verifying JWT tokens.

Constants

ALGORITHM_KEYS

Order is very important - first check for string keys, next for symbols

Attributes

token[R]

Public Class Methods

new(jwt, key, verify, options, &keyfinder) click to toggle source

Initializes a new Decode instance.

@param jwt [String] the JWT to decode. @param key [String, Array<String>] the key(s) to use for verification. @param verify [Boolean] whether to verify the token's signature. @param options [Hash] additional options for decoding and verification. @param keyfinder [Proc] an optional key finder block to dynamically find the key for verification. @raise [JWT::DecodeError] if decoding or verification fails.

# File lib/jwt/decode.rb, line 17
def initialize(jwt, key, verify, options, &keyfinder)
  raise JWT::DecodeError, 'Nil JSON web token' unless jwt

  @token = EncodedToken.new(jwt)
  @key = key
  @options = options
  @verify = verify
  @keyfinder = keyfinder
end

Public Instance Methods

decode_segments() click to toggle source

Decodes the JWT token and verifies its segments if verification is enabled.

@return [Array<Hash>] an array containing the decoded payload and header.

# File lib/jwt/decode.rb, line 30
def decode_segments
  validate_segment_count!
  if @verify
    verify_algo
    set_key
    verify_signature
    Claims::DecodeVerifier.verify!(token.payload, @options)
  end

  [token.payload, token.header]
end

Private Instance Methods

alg_in_header() click to toggle source
# File lib/jwt/decode.rb, line 116
def alg_in_header
  token.header['alg']
end
allowed_algorithms() click to toggle source
# File lib/jwt/decode.rb, line 87
def allowed_algorithms
  @allowed_algorithms ||= resolve_allowed_algorithms
end
allowed_and_valid_algorithms() click to toggle source
# File lib/jwt/decode.rb, line 69
def allowed_and_valid_algorithms
  @allowed_and_valid_algorithms ||= allowed_algorithms.select { |alg| alg.valid_alg?(alg_in_header) }
end
find_key() { |header, payload| ... } click to toggle source
# File lib/jwt/decode.rb, line 95
def find_key(&keyfinder)
  key = (keyfinder.arity == 2 ? yield(token.header, token.payload) : yield(token.header))
  # key can be of type [string, nil, OpenSSL::PKey, Array]
  return key if key && !Array(key).empty?

  raise JWT::DecodeError, 'No verification key available'
end
given_algorithms() click to toggle source
# File lib/jwt/decode.rb, line 79
def given_algorithms
  ALGORITHM_KEYS.each do |alg_key|
    alg = @options[alg_key]
    return Array(alg) if alg
  end
  []
end
none_algorithm?() click to toggle source
# File lib/jwt/decode.rb, line 112
def none_algorithm?
  alg_in_header == 'none'
end
resolve_allowed_algorithms() click to toggle source
# File lib/jwt/decode.rb, line 91
def resolve_allowed_algorithms
  given_algorithms.map { |alg| JWA.resolve(alg) }
end
set_key() click to toggle source
# File lib/jwt/decode.rb, line 61
def set_key
  @key = find_key(&@keyfinder) if @keyfinder
  @key = ::JWT::JWK::KeyFinder.new(jwks: @options[:jwks], allow_nil_kid: @options[:allow_nil_kid]).key_for(token.header['kid']) if @options[:jwks]
  return unless (x5c_options = @options[:x5c])

  @key = X5cKeyFinder.new(x5c_options[:root_certificates], x5c_options[:crls]).from(token.header['x5c'])
end
validate_segment_count!() click to toggle source
# File lib/jwt/decode.rb, line 103
def validate_segment_count!
  segment_count = token.jwt.count('.') + 1
  return if segment_count == 3
  return if !@verify && segment_count == 2 # If no verifying required, the signature is not needed
  return if segment_count == 2 && none_algorithm?

  raise JWT::DecodeError, 'Not enough or too many segments'
end
verify_algo() click to toggle source
# File lib/jwt/decode.rb, line 54
def verify_algo
  raise JWT::IncorrectAlgorithm, 'An algorithm must be specified' if allowed_algorithms.empty?
  raise JWT::DecodeError, 'Token header not a JSON object' unless token.header.is_a?(Hash)
  raise JWT::IncorrectAlgorithm, 'Token is missing alg header' unless alg_in_header
  raise JWT::IncorrectAlgorithm, 'Expected a different algorithm' if allowed_and_valid_algorithms.empty?
end
verify_signature() click to toggle source
# File lib/jwt/decode.rb, line 46
def verify_signature
  return if none_algorithm?

  raise JWT::DecodeError, 'No verification key available' unless @key

  token.verify_signature!(algorithm: allowed_and_valid_algorithms, key: @key)
end