class JWT::Decode

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

def alg_in_header

def alg_in_header
  token.header['alg']
end

def allowed_algorithms

def allowed_algorithms
  @allowed_algorithms ||= resolve_allowed_algorithms
end

def allowed_and_valid_algorithms

def allowed_and_valid_algorithms
  @allowed_and_valid_algorithms ||= allowed_algorithms.select { |alg| alg.valid_alg?(alg_in_header) }
end

def decode_segments

Returns:
  • (Array) - an array containing the decoded payload and header.
def decode_segments
  validate_segment_count!
  if @verify
    verify_algo
    set_key
    verify_signature
    Claims::DecodeVerifier.verify!(token.unverified_payload, @options)
  end
  [token.unverified_payload, token.header]
end

def find_key(&keyfinder)

def find_key(&keyfinder)
  key = (keyfinder.arity == 2 ? yield(token.header, token.unverified_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

def given_algorithms

def given_algorithms
  alg_key = ALGORITHM_KEYS.find { |key| @options[key] }
  Array(@options[alg_key])
end

def initialize(jwt, key, verify, options, &keyfinder)

Raises:
  • (JWT::DecodeError) - if decoding or verification fails.

Parameters:
  • keyfinder (Proc) -- an optional key finder block to dynamically find the key for verification.
  • options (Hash) -- additional options for decoding and verification.
  • verify (Boolean) -- whether to verify the token's signature.
  • key (String, Array) -- the key(s) to use for verification.
  • jwt (String) -- the JWT to decode.
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

def none_algorithm?

def none_algorithm?
  alg_in_header == 'none'
end

def resolve_allowed_algorithms

def resolve_allowed_algorithms
  given_algorithms.map { |alg| JWA.resolve(alg) }
end

def set_key

def set_key
  @key = find_key(&@keyfinder) if @keyfinder
  if @options[:jwks]
    @key = ::JWT::JWK::KeyFinder.new(
      jwks: @options[:jwks],
      allow_nil_kid: @options[:allow_nil_kid],
      key_fields: @options[:key_fields]
    ).call(token)
  end
  return unless (x5c_options = @options[:x5c])
  @key = X5cKeyFinder.new(x5c_options[:root_certificates], x5c_options[:crls]).from(token.header['x5c'])
end

def validate_segment_count!

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

def verify_algo

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

def verify_signature

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