class JWT::EncodedToken

Represents an encoded JWT token

Processing an encoded and signed token:

token = JWT::Token.new(payload: {pay: 'load'})
token.sign!(algorithm: 'HS256', key: 'secret')

encoded_token = JWT::EncodedToken.new(token.jwt)
encoded_token.verify_signature!(algorithm: 'HS256', key: 'secret')
encoded_token.payload # => {'pay' => 'load'}

Attributes

encoded_header[R]

Returns the encoded header of the JWT token.

@return [String] the encoded header.

encoded_payload[RW]

Sets or returns the encoded payload of the JWT token.

@return [String] the encoded payload.

encoded_signature[R]

Returns the encoded signature of the JWT token.

@return [String] the encoded signature.

jwt[R]

Returns the original token provided to the class. @return [String] The JWT token.

to_s[R]

Returns the original token provided to the class. @return [String] The JWT token.

Public Class Methods

new(jwt) click to toggle source

Initializes a new EncodedToken instance.

@param jwt [String] the encoded JWT token. @raise [ArgumentError] if the provided JWT is not a String.

# File lib/jwt/encoded_token.rb, line 25
def initialize(jwt)
  raise ArgumentError, 'Provided JWT must be a String' unless jwt.is_a?(String)

  @jwt = jwt
  @encoded_header, @encoded_payload, @encoded_signature = jwt.split('.')
end

Public Instance Methods

header() click to toggle source

Returns the decoded header of the JWT token.

@return [Hash] the header.

# File lib/jwt/encoded_token.rb, line 47
def header
  @header ||= parse_and_decode(@encoded_header)
end
payload() click to toggle source

Returns the payload of the JWT token.

@return [Hash] the payload.

# File lib/jwt/encoded_token.rb, line 59
def payload
  @payload ||= decode_payload
end
signature() click to toggle source

Returns the decoded signature of the JWT token.

@return [String] the decoded signature.

# File lib/jwt/encoded_token.rb, line 35
def signature
  @signature ||= ::JWT::Base64.url_decode(encoded_signature || '')
end
signing_input() click to toggle source

Returns the signing input of the JWT token.

@return [String] the signing input.

# File lib/jwt/encoded_token.rb, line 71
def signing_input
  [encoded_header, encoded_payload].join('.')
end
valid_signature?(algorithm:, key:) click to toggle source

Checks if the signature of the JWT token is valid.

@param algorithm [String, Array<String>, Object, Array<Object>] the algorithm(s) to use for verification. @param key [String, Array<String>] the key(s) to use for verification. @return [Boolean] true if the signature is valid, false otherwise.

# File lib/jwt/encoded_token.rb, line 98
def valid_signature?(algorithm:, key:)
  Array(JWA.resolve_and_sort(algorithms: algorithm, preferred_algorithm: header['alg'])).any? do |algo|
    Array(key).any? do |one_key|
      algo.verify(data: signing_input, signature: signature, verification_key: one_key)
    end
  end
end
verify_signature!(algorithm:, key: nil, key_finder: nil) click to toggle source

Verifies the signature of the JWT token.

@param algorithm [String, Array<String>, Object, Array<Object>] the algorithm(s) to use for verification. @param key [String, Array<String>] the key(s) to use for verification. @param key_finder [#call] an object responding to `call` to find the key for verification. @return [nil] @raise [JWT::VerificationError] if the signature verification fails. @raise [ArgumentError] if neither key nor key_finder is provided, or if both are provided.

# File lib/jwt/encoded_token.rb, line 83
def verify_signature!(algorithm:, key: nil, key_finder: nil)
  raise ArgumentError, 'Provide either key or key_finder, not both or neither' if key.nil? == key_finder.nil?

  key ||= key_finder.call(self)

  return if valid_signature?(algorithm: algorithm, key: key)

  raise JWT::VerificationError, 'Signature verification failed'
end

Private Instance Methods

decode_payload() click to toggle source
# File lib/jwt/encoded_token.rb, line 110
def decode_payload
  raise JWT::DecodeError, 'Encoded payload is empty' if encoded_payload == ''

  if unencoded_payload?
    verify_claims!(crit: ['b64'])
    return parse_unencoded(encoded_payload)
  end

  parse_and_decode(encoded_payload)
end
parse(segment) click to toggle source
# File lib/jwt/encoded_token.rb, line 133
def parse(segment)
  JWT::JSON.parse(segment)
rescue ::JSON::ParserError
  raise JWT::DecodeError, 'Invalid segment encoding'
end
parse_and_decode(segment) click to toggle source
# File lib/jwt/encoded_token.rb, line 125
def parse_and_decode(segment)
  parse(::JWT::Base64.url_decode(segment || ''))
end
parse_unencoded(segment) click to toggle source
# File lib/jwt/encoded_token.rb, line 129
def parse_unencoded(segment)
  parse(segment)
end
unencoded_payload?() click to toggle source
# File lib/jwt/encoded_token.rb, line 121
def unencoded_payload?
  header['b64'] == false
end