Class: JWT::EncodedToken

Inherits:
Object
  • Object
show all
Defined in:
lib/jwt/encoded_token.rb

Overview

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'}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(jwt) ⇒ EncodedToken

Initializes a new EncodedToken instance.

Parameters:

  • jwt (String)

    the encoded JWT token.

Raises:

  • (ArgumentError)

    if the provided JWT is not a String.



43
44
45
46
47
48
49
50
51
# File 'lib/jwt/encoded_token.rb', line 43

def initialize(jwt)
  raise ArgumentError, 'Provided JWT must be a String' unless jwt.is_a?(String)

  @jwt = jwt
  @signature_verified = false
  @claims_verified    = false

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

Instance Attribute Details

#encoded_headerString (readonly)

Returns the encoded header of the JWT token.

Returns:

  • (String)

    the encoded header.



75
76
77
# File 'lib/jwt/encoded_token.rb', line 75

def encoded_header
  @encoded_header
end

#encoded_payloadString

Sets or returns the encoded payload of the JWT token.

Returns:

  • (String)

    the encoded payload.



97
98
99
# File 'lib/jwt/encoded_token.rb', line 97

def encoded_payload
  @encoded_payload
end

#encoded_signatureString (readonly)

Returns the encoded signature of the JWT token.

Returns:

  • (String)

    the encoded signature.



63
64
65
# File 'lib/jwt/encoded_token.rb', line 63

def encoded_signature
  @encoded_signature
end

#jwtString (readonly) Also known as: to_s

Returns the original token provided to the class.

Returns:

  • (String)

    The JWT token.



37
38
39
# File 'lib/jwt/encoded_token.rb', line 37

def jwt
  @jwt
end

Instance Method Details

#claim_errors(*options) ⇒ Array<Symbol>

Returns the errors of the claims of the token.

Parameters:

  • options (Array<Symbol>, Hash)

    the claims to verify. By default, it checks the ‘exp’ claim.

Returns:

  • (Array<Symbol>)

    the errors of the claims.



182
183
184
# File 'lib/jwt/encoded_token.rb', line 182

def claim_errors(*options)
  Claims::Verifier.errors(ClaimsContext.new(self), *claims_options(options))
end

#headerHash

Returns the decoded header of the JWT token.

Returns:

  • (Hash)

    the header.



68
69
70
# File 'lib/jwt/encoded_token.rb', line 68

def header
  @header ||= parse_and_decode(@encoded_header)
end

#payloadHash

Returns the payload of the JWT token. Access requires the signature and claims to have been verified.

Returns:

  • (Hash)

    the payload.

Raises:



81
82
83
84
85
86
# File 'lib/jwt/encoded_token.rb', line 81

def payload
  raise JWT::DecodeError, 'Verify the token signature before accessing the payload' unless @signature_verified
  raise JWT::DecodeError, 'Verify the token claims before accessing the payload' unless @claims_verified

  decoded_payload
end

#signatureString

Returns the decoded signature of the JWT token.

Returns:

  • (String)

    the decoded signature.



56
57
58
# File 'lib/jwt/encoded_token.rb', line 56

def signature
  @signature ||= ::JWT::Base64.url_decode(encoded_signature || '')
end

#signing_inputString

Returns the signing input of the JWT token.

Returns:

  • (String)

    the signing input.



102
103
104
# File 'lib/jwt/encoded_token.rb', line 102

def signing_input
  [encoded_header, encoded_payload].join('.')
end

#unverified_payloadHash

Returns the payload of the JWT token without requiring the signature to have been verified.

Returns:

  • (Hash)

    the payload.



90
91
92
# File 'lib/jwt/encoded_token.rb', line 90

def unverified_payload
  decoded_payload
end

#valid?(signature:, claims: nil) ⇒ Boolean

Returns true if the signature and claims are valid, false otherwise.

Parameters:

  • signature (Hash)

    the parameters for signature verification (see #verify_signature!).

  • claims (Array<Symbol>, Hash) (defaults to: nil)

    the claims to verify (see #verify_claims!).

Returns:

  • (Boolean)

    true if the signature and claims are valid, false otherwise.



128
129
130
131
# File 'lib/jwt/encoded_token.rb', line 128

def valid?(signature:, claims: nil)
  valid_signature?(**signature) &&
    (claims.is_a?(Array) ? valid_claims?(*claims) : valid_claims?(claims))
end

#valid_claims?(*options) ⇒ Boolean

Returns whether the claims of the token are valid.

Parameters:

  • options (Array<Symbol>, Hash)

    the claims to verify. By default, it checks the ‘exp’ claim.

Returns:

  • (Boolean)

    whether the claims are valid.



189
190
191
# File 'lib/jwt/encoded_token.rb', line 189

def valid_claims?(*options)
  claim_errors(*claims_options(options)).empty?.tap { |verified| @claims_verified = verified }
end

#valid_signature?(algorithm: nil, key: nil, key_finder: nil) ⇒ Boolean

Checks if the signature of the JWT token is valid.

Parameters:

  • algorithm (String, Array<String>, Object, Array<Object>) (defaults to: nil)

    the algorithm(s) to use for verification.

  • key (String, Array<String>, JWT::JWK::KeyBase, Array<JWT::JWK::KeyBase>) (defaults to: nil)

    the key(s) to use for verification.

  • key_finder (#call) (defaults to: nil)

    an object responding to ‘call` to find the key for verification.

Returns:

  • (Boolean)

    true if the signature is valid, false otherwise.

Raises:

  • (ArgumentError)


153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/jwt/encoded_token.rb', line 153

def valid_signature?(algorithm: nil, key: nil, key_finder: nil)
  raise ArgumentError, 'Provide either key or key_finder, not both or neither' if key.nil? == key_finder.nil?

  keys      = Array(key || key_finder.call(self))
  verifiers = JWA.create_verifiers(algorithms: algorithm, keys: keys, preferred_algorithm: header['alg'])

  raise JWT::VerificationError, 'No algorithm provided' if verifiers.empty?

  valid = verifiers.any? do |jwa|
    jwa.verify(data: signing_input, signature: signature)
  end
  valid.tap { |verified| @signature_verified = verified }
end

#verify!(signature:, claims: nil) ⇒ nil

Verifies the token signature and claims. By default it verifies the ‘exp’ claim.

Examples:

encoded_token.verify!(signature: { algorithm: 'HS256', key: 'secret' }, claims: [:exp])

Parameters:

  • signature (Hash)

    the parameters for signature verification (see #verify_signature!).

  • claims (Array<Symbol>, Hash) (defaults to: nil)

    the claims to verify (see #verify_claims!).

Returns:

  • (nil)

Raises:



116
117
118
119
120
# File 'lib/jwt/encoded_token.rb', line 116

def verify!(signature:, claims: nil)
  verify_signature!(**signature)
  claims.is_a?(Array) ? verify_claims!(*claims) : verify_claims!(claims)
  nil
end

#verify_claims!(*options) ⇒ Object

Verifies the claims of the token.

Parameters:

  • options (Array<Symbol>, Hash)

    the claims to verify. By default, it checks the ‘exp’ claim.

Raises:



170
171
172
173
174
175
176
177
# File 'lib/jwt/encoded_token.rb', line 170

def verify_claims!(*options)
  Claims::Verifier.verify!(ClaimsContext.new(self), *claims_options(options)).tap do
    @claims_verified = true
  end
rescue StandardError
  @claims_verified = false
  raise
end

#verify_signature!(algorithm:, key: nil, key_finder: nil) ⇒ nil

Verifies the signature of the JWT token.

Parameters:

  • algorithm (String, Array<String>, Object, Array<Object>)

    the algorithm(s) to use for verification.

  • key (String, Array<String>) (defaults to: nil)

    the key(s) to use for verification.

  • key_finder (#call) (defaults to: nil)

    an object responding to ‘call` to find the key for verification.

Returns:

  • (nil)

Raises:

  • (JWT::VerificationError)

    if the signature verification fails.

  • (ArgumentError)

    if neither key nor key_finder is provided, or if both are provided.



141
142
143
144
145
# File 'lib/jwt/encoded_token.rb', line 141

def verify_signature!(algorithm:, key: nil, key_finder: nil)
  return if valid_signature?(algorithm: algorithm, key: key, key_finder: key_finder)

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