jwt 2.9.1 → 2.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -0
  3. data/README.md +170 -82
  4. data/lib/jwt/base64.rb +3 -0
  5. data/lib/jwt/claims/audience.rb +10 -0
  6. data/lib/jwt/claims/crit.rb +35 -0
  7. data/lib/jwt/claims/decode_verifier.rb +40 -0
  8. data/lib/jwt/claims/expiration.rb +10 -0
  9. data/lib/jwt/claims/issued_at.rb +7 -0
  10. data/lib/jwt/claims/issuer.rb +10 -0
  11. data/lib/jwt/claims/jwt_id.rb +10 -0
  12. data/lib/jwt/claims/not_before.rb +10 -0
  13. data/lib/jwt/claims/numeric.rb +47 -13
  14. data/lib/jwt/claims/required.rb +10 -0
  15. data/lib/jwt/claims/subject.rb +10 -0
  16. data/lib/jwt/claims/verification_methods.rb +20 -0
  17. data/lib/jwt/claims/verifier.rb +61 -0
  18. data/lib/jwt/claims.rb +52 -16
  19. data/lib/jwt/claims_validator.rb +18 -0
  20. data/lib/jwt/configuration/container.rb +20 -0
  21. data/lib/jwt/configuration/decode_configuration.rb +24 -0
  22. data/lib/jwt/configuration/jwk_configuration.rb +1 -0
  23. data/lib/jwt/configuration.rb +8 -0
  24. data/lib/jwt/decode.rb +28 -67
  25. data/lib/jwt/deprecations.rb +1 -0
  26. data/lib/jwt/encode.rb +17 -56
  27. data/lib/jwt/encoded_token.rb +139 -0
  28. data/lib/jwt/error.rb +34 -0
  29. data/lib/jwt/json.rb +1 -1
  30. data/lib/jwt/jwa/compat.rb +32 -0
  31. data/lib/jwt/jwa/ecdsa.rb +7 -6
  32. data/lib/jwt/jwa/eddsa.rb +7 -6
  33. data/lib/jwt/jwa/hmac.rb +6 -3
  34. data/lib/jwt/jwa/hmac_rbnacl.rb +5 -0
  35. data/lib/jwt/jwa/hmac_rbnacl_fixed.rb +5 -0
  36. data/lib/jwt/jwa/none.rb +1 -0
  37. data/lib/jwt/jwa/ps.rb +2 -3
  38. data/lib/jwt/jwa/rsa.rb +2 -3
  39. data/lib/jwt/jwa/signing_algorithm.rb +4 -0
  40. data/lib/jwt/jwa/unsupported.rb +1 -0
  41. data/lib/jwt/jwa/wrapper.rb +1 -0
  42. data/lib/jwt/jwa.rb +17 -4
  43. data/lib/jwt/jwk/ec.rb +2 -3
  44. data/lib/jwt/jwk/hmac.rb +2 -3
  45. data/lib/jwt/jwk/key_base.rb +1 -0
  46. data/lib/jwt/jwk/key_finder.rb +1 -0
  47. data/lib/jwt/jwk/kid_as_key_digest.rb +1 -0
  48. data/lib/jwt/jwk/okp_rbnacl.rb +3 -4
  49. data/lib/jwt/jwk/rsa.rb +2 -3
  50. data/lib/jwt/jwk/set.rb +2 -0
  51. data/lib/jwt/jwk.rb +1 -0
  52. data/lib/jwt/token.rb +112 -0
  53. data/lib/jwt/verify.rb +40 -0
  54. data/lib/jwt/version.rb +30 -9
  55. data/lib/jwt.rb +19 -0
  56. metadata +13 -7
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JWT
4
+ module Claims
5
+ # Responsible of validation the crit header
6
+ class Crit
7
+ # Initializes a new Crit instance.
8
+ #
9
+ # @param expected_crits [String] the expected crit header values for the JWT token.
10
+ def initialize(expected_crits:)
11
+ @expected_crits = Array(expected_crits)
12
+ end
13
+
14
+ # Verifies the critical claim ('crit') in the JWT token header.
15
+ #
16
+ # @param context [Object] the context containing the JWT payload and header.
17
+ # @param _args [Hash] additional arguments (not used).
18
+ # @raise [JWT::InvalidCritError] if the crit claim is invalid.
19
+ # @return [nil]
20
+ def verify!(context:, **_args)
21
+ raise(JWT::InvalidCritError, 'Crit header missing') unless context.header['crit']
22
+ raise(JWT::InvalidCritError, 'Crit header should be an array') unless context.header['crit'].is_a?(Array)
23
+
24
+ missing = (expected_crits - context.header['crit'])
25
+ raise(JWT::InvalidCritError, "Crit header missing expected values: #{missing.join(', ')}") if missing.any?
26
+
27
+ nil
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :expected_crits
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JWT
4
+ module Claims
5
+ # Context class to contain the data passed to individual claim validators
6
+ #
7
+ # @api private
8
+ VerificationContext = Struct.new(:payload, keyword_init: true)
9
+
10
+ # Verifiers to support the ::JWT.decode method
11
+ #
12
+ # @api private
13
+ module DecodeVerifier
14
+ VERIFIERS = {
15
+ verify_expiration: ->(options) { Claims::Expiration.new(leeway: options[:exp_leeway] || options[:leeway]) },
16
+ verify_not_before: ->(options) { Claims::NotBefore.new(leeway: options[:nbf_leeway] || options[:leeway]) },
17
+ verify_iss: ->(options) { options[:iss] && Claims::Issuer.new(issuers: options[:iss]) },
18
+ verify_iat: ->(*) { Claims::IssuedAt.new },
19
+ verify_jti: ->(options) { Claims::JwtId.new(validator: options[:verify_jti]) },
20
+ verify_aud: ->(options) { options[:aud] && Claims::Audience.new(expected_audience: options[:aud]) },
21
+ verify_sub: ->(options) { options[:sub] && Claims::Subject.new(expected_subject: options[:sub]) },
22
+ required_claims: ->(options) { Claims::Required.new(required_claims: options[:required_claims]) }
23
+ }.freeze
24
+
25
+ private_constant(:VERIFIERS)
26
+
27
+ class << self
28
+ # @api private
29
+ def verify!(payload, options)
30
+ VERIFIERS.each do |key, verifier_builder|
31
+ next unless options[key] || options[key.to_s]
32
+
33
+ verifier_builder&.call(options)&.verify!(context: VerificationContext.new(payload: payload))
34
+ end
35
+ nil
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -2,11 +2,21 @@
2
2
 
3
3
  module JWT
4
4
  module Claims
5
+ # The Expiration class is responsible for validating the expiration claim ('exp') in a JWT token.
5
6
  class Expiration
7
+ # Initializes a new Expiration instance.
8
+ #
9
+ # @param leeway [Integer] the amount of leeway (in seconds) to allow when validating the expiration time. Default: 0.
6
10
  def initialize(leeway:)
7
11
  @leeway = leeway || 0
8
12
  end
9
13
 
14
+ # Verifies the expiration claim ('exp') in the JWT token.
15
+ #
16
+ # @param context [Object] the context containing the JWT payload.
17
+ # @param _args [Hash] additional arguments (not used).
18
+ # @raise [JWT::ExpiredSignature] if the token has expired.
19
+ # @return [nil]
10
20
  def verify!(context:, **_args)
11
21
  return unless context.payload.is_a?(Hash)
12
22
  return unless context.payload.key?('exp')
@@ -2,7 +2,14 @@
2
2
 
3
3
  module JWT
4
4
  module Claims
5
+ # The IssuedAt class is responsible for validating the issued at claim ('iat') in a JWT token.
5
6
  class IssuedAt
7
+ # Verifies the issued at claim ('iat') in the JWT token.
8
+ #
9
+ # @param context [Object] the context containing the JWT payload.
10
+ # @param _args [Hash] additional arguments (not used).
11
+ # @raise [JWT::InvalidIatError] if the issued at claim is invalid.
12
+ # @return [nil]
6
13
  def verify!(context:, **_args)
7
14
  return unless context.payload.is_a?(Hash)
8
15
  return unless context.payload.key?('iat')
@@ -2,11 +2,21 @@
2
2
 
3
3
  module JWT
4
4
  module Claims
5
+ # The Issuer class is responsible for validating the issuer claim ('iss') in a JWT token.
5
6
  class Issuer
7
+ # Initializes a new Issuer instance.
8
+ #
9
+ # @param issuers [String, Symbol, Array<String, Symbol>] the expected issuer(s) for the JWT token.
6
10
  def initialize(issuers:)
7
11
  @issuers = Array(issuers).map { |item| item.is_a?(Symbol) ? item.to_s : item }
8
12
  end
9
13
 
14
+ # Verifies the issuer claim ('iss') in the JWT token.
15
+ #
16
+ # @param context [Object] the context containing the JWT payload.
17
+ # @param _args [Hash] additional arguments (not used).
18
+ # @raise [JWT::InvalidIssuerError] if the issuer claim is invalid.
19
+ # @return [nil]
10
20
  def verify!(context:, **_args)
11
21
  case (iss = context.payload['iss'])
12
22
  when *issuers
@@ -2,11 +2,21 @@
2
2
 
3
3
  module JWT
4
4
  module Claims
5
+ # The JwtId class is responsible for validating the JWT ID claim ('jti') in a JWT token.
5
6
  class JwtId
7
+ # Initializes a new JwtId instance.
8
+ #
9
+ # @param validator [#call] an object responding to `call` to validate the JWT ID.
6
10
  def initialize(validator:)
7
11
  @validator = validator
8
12
  end
9
13
 
14
+ # Verifies the JWT ID claim ('jti') in the JWT token.
15
+ #
16
+ # @param context [Object] the context containing the JWT payload.
17
+ # @param _args [Hash] additional arguments (not used).
18
+ # @raise [JWT::InvalidJtiError] if the JWT ID claim is invalid or missing.
19
+ # @return [nil]
10
20
  def verify!(context:, **_args)
11
21
  jti = context.payload['jti']
12
22
  if validator.respond_to?(:call)
@@ -2,11 +2,21 @@
2
2
 
3
3
  module JWT
4
4
  module Claims
5
+ # The NotBefore class is responsible for validating the 'nbf' (Not Before) claim in a JWT token.
5
6
  class NotBefore
7
+ # Initializes a new NotBefore instance.
8
+ #
9
+ # @param leeway [Integer] the amount of leeway (in seconds) to allow when validating the 'nbf' claim. Defaults to 0.
6
10
  def initialize(leeway:)
7
11
  @leeway = leeway || 0
8
12
  end
9
13
 
14
+ # Verifies the 'nbf' (Not Before) claim in the JWT token.
15
+ #
16
+ # @param context [Object] the context containing the JWT payload.
17
+ # @param _args [Hash] additional arguments (not used).
18
+ # @raise [JWT::ImmatureSignature] if the 'nbf' claim has not been reached.
19
+ # @return [nil]
10
20
  def verify!(context:, **_args)
11
21
  return unless context.payload.is_a?(Hash)
12
22
  return unless context.payload.key?('nbf')
@@ -2,41 +2,75 @@
2
2
 
3
3
  module JWT
4
4
  module Claims
5
+ # The Numeric class is responsible for validating numeric claims in a JWT token.
6
+ # The numeric claims are: exp, iat and nbf
5
7
  class Numeric
6
- def self.verify!(payload:, **_args)
7
- return unless payload.is_a?(Hash)
8
+ # The Compat class provides backward compatibility for numeric claim validation.
9
+ # @api private
10
+ class Compat
11
+ def initialize(payload)
12
+ @payload = payload
13
+ end
8
14
 
9
- new(payload).verify!
15
+ def verify!
16
+ JWT::Claims.verify_payload!(@payload, :numeric)
17
+ end
10
18
  end
11
19
 
20
+ # List of numeric claims that can be validated.
12
21
  NUMERIC_CLAIMS = %i[
13
22
  exp
14
23
  iat
15
24
  nbf
16
25
  ].freeze
17
26
 
18
- def initialize(payload)
19
- @payload = payload.transform_keys(&:to_sym)
27
+ private_constant(:NUMERIC_CLAIMS)
28
+
29
+ # @api private
30
+ def self.new(*args)
31
+ return super if args.empty?
32
+
33
+ Deprecations.warning('Calling ::JWT::Claims::Numeric.new with the payload will be removed in the next major version of ruby-jwt')
34
+ Compat.new(*args)
20
35
  end
21
36
 
22
- def verify!
23
- validate_numeric_claims
37
+ # Verifies the numeric claims in the JWT context.
38
+ #
39
+ # @param context [Object] the context containing the JWT payload.
40
+ # @raise [JWT::InvalidClaimError] if any numeric claim is invalid.
41
+ # @return [nil]
42
+ def verify!(context:)
43
+ validate_numeric_claims(context.payload)
44
+ end
24
45
 
25
- true
46
+ # Verifies the numeric claims in the JWT payload.
47
+ #
48
+ # @param payload [Hash] the JWT payload containing the claims.
49
+ # @param _args [Hash] additional arguments (not used).
50
+ # @raise [JWT::InvalidClaimError] if any numeric claim is invalid.
51
+ # @return [nil]
52
+ # @deprecated The ::JWT::Claims::Numeric.verify! method will be removed in the next major version of ruby-jwt
53
+ def self.verify!(payload:, **_args)
54
+ Deprecations.warning('The ::JWT::Claims::Numeric.verify! method will be removed in the next major version of ruby-jwt.')
55
+ JWT::Claims.verify_payload!(payload, :numeric)
26
56
  end
27
57
 
28
58
  private
29
59
 
30
- def validate_numeric_claims
60
+ def validate_numeric_claims(payload)
31
61
  NUMERIC_CLAIMS.each do |claim|
32
- validate_is_numeric(claim) if @payload.key?(claim)
62
+ validate_is_numeric(payload, claim)
33
63
  end
34
64
  end
35
65
 
36
- def validate_is_numeric(claim)
37
- return if @payload[claim].is_a?(::Numeric)
66
+ def validate_is_numeric(payload, claim)
67
+ return unless payload.is_a?(Hash)
68
+ return unless payload.key?(claim) ||
69
+ payload.key?(claim.to_s)
70
+
71
+ return if payload[claim].is_a?(::Numeric) || payload[claim.to_s].is_a?(::Numeric)
38
72
 
39
- raise InvalidPayload, "#{claim} claim must be a Numeric value but it is a #{@payload[claim].class}"
73
+ raise InvalidPayload, "#{claim} claim must be a Numeric value but it is a #{(payload[claim] || payload[claim.to_s]).class}"
40
74
  end
41
75
  end
42
76
  end
@@ -2,11 +2,21 @@
2
2
 
3
3
  module JWT
4
4
  module Claims
5
+ # The Required class is responsible for validating that all required claims are present in a JWT token.
5
6
  class Required
7
+ # Initializes a new Required instance.
8
+ #
9
+ # @param required_claims [Array<String>] the list of required claims.
6
10
  def initialize(required_claims:)
7
11
  @required_claims = required_claims
8
12
  end
9
13
 
14
+ # Verifies that all required claims are present in the JWT payload.
15
+ #
16
+ # @param context [Object] the context containing the JWT payload.
17
+ # @param _args [Hash] additional arguments (not used).
18
+ # @raise [JWT::MissingRequiredClaim] if any required claim is missing.
19
+ # @return [nil]
10
20
  def verify!(context:, **_args)
11
21
  required_claims.each do |required_claim|
12
22
  next if context.payload.is_a?(Hash) && context.payload.key?(required_claim)
@@ -2,11 +2,21 @@
2
2
 
3
3
  module JWT
4
4
  module Claims
5
+ # The Subject class is responsible for validating the subject claim ('sub') in a JWT token.
5
6
  class Subject
7
+ # Initializes a new Subject instance.
8
+ #
9
+ # @param expected_subject [String] the expected subject for the JWT token.
6
10
  def initialize(expected_subject:)
7
11
  @expected_subject = expected_subject.to_s
8
12
  end
9
13
 
14
+ # Verifies the subject claim ('sub') in the JWT token.
15
+ #
16
+ # @param context [Object] the context containing the JWT payload.
17
+ # @param _args [Hash] additional arguments (not used).
18
+ # @raise [JWT::InvalidSubError] if the subject claim is invalid.
19
+ # @return [nil]
10
20
  def verify!(context:, **_args)
11
21
  sub = context.payload['sub']
12
22
  raise(JWT::InvalidSubError, "Invalid subject. Expected #{expected_subject}, received #{sub || '<none>'}") unless sub.to_s == expected_subject
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JWT
4
+ module Claims
5
+ # @api private
6
+ module VerificationMethods
7
+ def verify_claims!(*options)
8
+ Verifier.verify!(self, *options)
9
+ end
10
+
11
+ def claim_errors(*options)
12
+ Verifier.errors(self, *options)
13
+ end
14
+
15
+ def valid_claims?(*options)
16
+ claim_errors(*options).empty?
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JWT
4
+ module Claims
5
+ # @api private
6
+ module Verifier
7
+ VERIFIERS = {
8
+ exp: ->(options) { Claims::Expiration.new(leeway: options.dig(:exp, :leeway)) },
9
+ nbf: ->(options) { Claims::NotBefore.new(leeway: options.dig(:nbf, :leeway)) },
10
+ iss: ->(options) { Claims::Issuer.new(issuers: options[:iss]) },
11
+ iat: ->(*) { Claims::IssuedAt.new },
12
+ jti: ->(options) { Claims::JwtId.new(validator: options[:jti]) },
13
+ aud: ->(options) { Claims::Audience.new(expected_audience: options[:aud]) },
14
+ sub: ->(options) { Claims::Subject.new(expected_subject: options[:sub]) },
15
+ crit: ->(options) { Claims::Crit.new(expected_crits: options[:crit]) },
16
+ required: ->(options) { Claims::Required.new(required_claims: options[:required]) },
17
+ numeric: ->(*) { Claims::Numeric.new }
18
+ }.freeze
19
+
20
+ private_constant(:VERIFIERS)
21
+
22
+ class << self
23
+ # @api private
24
+ def verify!(context, *options)
25
+ iterate_verifiers(*options) do |verifier, verifier_options|
26
+ verify_one!(context, verifier, verifier_options)
27
+ end
28
+ nil
29
+ end
30
+
31
+ # @api private
32
+ def errors(context, *options)
33
+ errors = []
34
+ iterate_verifiers(*options) do |verifier, verifier_options|
35
+ verify_one!(context, verifier, verifier_options)
36
+ rescue ::JWT::DecodeError => e
37
+ errors << Error.new(message: e.message)
38
+ end
39
+ errors
40
+ end
41
+
42
+ private
43
+
44
+ def iterate_verifiers(*options)
45
+ options.each do |element|
46
+ if element.is_a?(Hash)
47
+ element.each_key { |key| yield(key, element) }
48
+ else
49
+ yield(element, {})
50
+ end
51
+ end
52
+ end
53
+
54
+ def verify_one!(context, verifier, options)
55
+ verifier_builder = VERIFIERS.fetch(verifier) { raise ArgumentError, "#{verifier} not a valid claim verifier" }
56
+ verifier_builder.call(options || {}).verify!(context: context)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
data/lib/jwt/claims.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'claims/audience'
4
+ require_relative 'claims/crit'
5
+ require_relative 'claims/decode_verifier'
4
6
  require_relative 'claims/expiration'
5
7
  require_relative 'claims/issued_at'
6
8
  require_relative 'claims/issuer'
@@ -9,29 +11,63 @@ require_relative 'claims/not_before'
9
11
  require_relative 'claims/numeric'
10
12
  require_relative 'claims/required'
11
13
  require_relative 'claims/subject'
14
+ require_relative 'claims/verification_methods'
15
+ require_relative 'claims/verifier'
12
16
 
13
17
  module JWT
18
+ # JWT Claim verifications
19
+ # https://datatracker.ietf.org/doc/html/rfc7519#section-4
20
+ #
21
+ # Verification is supported for the following claims:
22
+ # exp
23
+ # nbf
24
+ # iss
25
+ # iat
26
+ # jti
27
+ # aud
28
+ # sub
29
+ # required
30
+ # numeric
14
31
  module Claims
15
- VerificationContext = Struct.new(:payload, keyword_init: true)
16
-
17
- VERIFIERS = {
18
- verify_expiration: ->(options) { Claims::Expiration.new(leeway: options[:exp_leeway] || options[:leeway]) },
19
- verify_not_before: ->(options) { Claims::NotBefore.new(leeway: options[:nbf_leeway] || options[:leeway]) },
20
- verify_iss: ->(options) { options[:iss] && Claims::Issuer.new(issuers: options[:iss]) },
21
- verify_iat: ->(*) { Claims::IssuedAt.new },
22
- verify_jti: ->(options) { Claims::JwtId.new(validator: options[:verify_jti]) },
23
- verify_aud: ->(options) { options[:aud] && Claims::Audience.new(expected_audience: options[:aud]) },
24
- verify_sub: ->(options) { options[:sub] && Claims::Subject.new(expected_subject: options[:sub]) },
25
- required_claims: ->(options) { Claims::Required.new(required_claims: options[:required_claims]) }
26
- }.freeze
32
+ # Represents a claim verification error
33
+ Error = Struct.new(:message, keyword_init: true)
27
34
 
28
35
  class << self
36
+ # @deprecated Use {verify_payload!} instead. Will be removed in the next major version of ruby-jwt.
29
37
  def verify!(payload, options)
30
- VERIFIERS.each do |key, verifier_builder|
31
- next unless options[key]
38
+ Deprecations.warning('The ::JWT::Claims.verify! method is deprecated will be removed in the next major version of ruby-jwt')
39
+ DecodeVerifier.verify!(payload, options)
40
+ end
41
+
42
+ # Checks if the claims in the JWT payload are valid.
43
+ # @example
44
+ #
45
+ # ::JWT::Claims.verify_payload!({"exp" => Time.now.to_i + 10}, :exp)
46
+ # ::JWT::Claims.verify_payload!({"exp" => Time.now.to_i - 10}, exp: { leeway: 11})
47
+ #
48
+ # @param payload [Hash] the JWT payload.
49
+ # @param options [Array] the options for verifying the claims.
50
+ # @return [void]
51
+ # @raise [JWT::DecodeError] if any claim is invalid.
52
+ def verify_payload!(payload, *options)
53
+ Verifier.verify!(VerificationContext.new(payload: payload), *options)
54
+ end
55
+
56
+ # Checks if the claims in the JWT payload are valid.
57
+ #
58
+ # @param payload [Hash] the JWT payload.
59
+ # @param options [Array] the options for verifying the claims.
60
+ # @return [Boolean] true if the claims are valid, false otherwise
61
+ def valid_payload?(payload, *options)
62
+ payload_errors(payload, *options).empty?
63
+ end
32
64
 
33
- verifier_builder&.call(options)&.verify!(context: VerificationContext.new(payload: payload))
34
- end
65
+ # Returns the errors in the claims of the JWT token.
66
+ #
67
+ # @param options [Array] the options for verifying the claims.
68
+ # @return [Array<JWT::Claims::Error>] the errors in the claims of the JWT
69
+ def payload_errors(payload, *options)
70
+ Verifier.errors(VerificationContext.new(payload: payload), *options)
35
71
  end
36
72
  end
37
73
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JWT
4
+ # @deprecated Use `Claims.verify_payload!` directly instead.
5
+ class ClaimsValidator
6
+ # @deprecated Use `Claims.verify_payload!` directly instead.
7
+ def initialize(payload)
8
+ Deprecations.warning('The ::JWT::ClaimsValidator class is deprecated and will be removed in the next major version of ruby-jwt')
9
+ @payload = payload
10
+ end
11
+
12
+ # @deprecated Use `Claims.verify_payload!` directly instead.
13
+ def validate!
14
+ Claims.verify_payload!(@payload, :numeric)
15
+ true
16
+ end
17
+ end
18
+ end
@@ -5,14 +5,28 @@ require_relative 'jwk_configuration'
5
5
 
6
6
  module JWT
7
7
  module Configuration
8
+ # The Container class holds the configuration settings for JWT.
8
9
  class Container
10
+ # @!attribute [rw] decode
11
+ # @return [DecodeConfiguration] the decode configuration.
12
+ # @!attribute [rw] jwk
13
+ # @return [JwkConfiguration] the JWK configuration.
14
+ # @!attribute [rw] strict_base64_decoding
15
+ # @return [Boolean] whether strict Base64 decoding is enabled.
9
16
  attr_accessor :decode, :jwk, :strict_base64_decoding
17
+
18
+ # @!attribute [r] deprecation_warnings
19
+ # @return [Symbol] the deprecation warnings setting.
10
20
  attr_reader :deprecation_warnings
11
21
 
22
+ # Initializes a new Container instance and resets the configuration.
12
23
  def initialize
13
24
  reset!
14
25
  end
15
26
 
27
+ # Resets the configuration to default values.
28
+ #
29
+ # @return [void]
16
30
  def reset!
17
31
  @decode = DecodeConfiguration.new
18
32
  @jwk = JwkConfiguration.new
@@ -22,6 +36,12 @@ module JWT
22
36
  end
23
37
 
24
38
  DEPRECATION_WARNINGS_VALUES = %i[once warn silent].freeze
39
+ private_constant(:DEPRECATION_WARNINGS_VALUES)
40
+ # Sets the deprecation warnings setting.
41
+ #
42
+ # @param value [Symbol] the deprecation warnings setting. Must be one of `:once`, `:warn`, or `:silent`.
43
+ # @raise [ArgumentError] if the value is not one of the supported values.
44
+ # @return [void]
25
45
  def deprecation_warnings=(value)
26
46
  raise ArgumentError, "Invalid deprecation_warnings value #{value}. Supported values: #{DEPRECATION_WARNINGS_VALUES}" unless DEPRECATION_WARNINGS_VALUES.include?(value)
27
47
 
@@ -2,7 +2,29 @@
2
2
 
3
3
  module JWT
4
4
  module Configuration
5
+ # The DecodeConfiguration class holds the configuration settings for decoding JWT tokens.
5
6
  class DecodeConfiguration
7
+ # @!attribute [rw] verify_expiration
8
+ # @return [Boolean] whether to verify the expiration claim.
9
+ # @!attribute [rw] verify_not_before
10
+ # @return [Boolean] whether to verify the not before claim.
11
+ # @!attribute [rw] verify_iss
12
+ # @return [Boolean] whether to verify the issuer claim.
13
+ # @!attribute [rw] verify_iat
14
+ # @return [Boolean] whether to verify the issued at claim.
15
+ # @!attribute [rw] verify_jti
16
+ # @return [Boolean] whether to verify the JWT ID claim.
17
+ # @!attribute [rw] verify_aud
18
+ # @return [Boolean] whether to verify the audience claim.
19
+ # @!attribute [rw] verify_sub
20
+ # @return [Boolean] whether to verify the subject claim.
21
+ # @!attribute [rw] leeway
22
+ # @return [Integer] the leeway in seconds for time-based claims.
23
+ # @!attribute [rw] algorithms
24
+ # @return [Array<String>] the list of acceptable algorithms.
25
+ # @!attribute [rw] required_claims
26
+ # @return [Array<String>] the list of required claims.
27
+
6
28
  attr_accessor :verify_expiration,
7
29
  :verify_not_before,
8
30
  :verify_iss,
@@ -14,6 +36,7 @@ module JWT
14
36
  :algorithms,
15
37
  :required_claims
16
38
 
39
+ # Initializes a new DecodeConfiguration instance with default settings.
17
40
  def initialize
18
41
  @verify_expiration = true
19
42
  @verify_not_before = true
@@ -27,6 +50,7 @@ module JWT
27
50
  @required_claims = []
28
51
  end
29
52
 
53
+ # @api private
30
54
  def to_h
31
55
  {
32
56
  verify_expiration: verify_expiration,
@@ -5,6 +5,7 @@ require_relative '../jwk/thumbprint'
5
5
 
6
6
  module JWT
7
7
  module Configuration
8
+ # @api private
8
9
  class JwkConfiguration
9
10
  def initialize
10
11
  self.kid_generator_type = :key_digest
@@ -3,11 +3,19 @@
3
3
  require_relative 'configuration/container'
4
4
 
5
5
  module JWT
6
+ # The Configuration module provides methods to configure JWT settings.
6
7
  module Configuration
8
+ # Configures the JWT settings.
9
+ #
10
+ # @yield [config] Gives the current configuration to the block.
11
+ # @yieldparam config [JWT::Configuration::Container] the configuration container.
7
12
  def configure
8
13
  yield(configuration)
9
14
  end
10
15
 
16
+ # Returns the JWT configuration container.
17
+ #
18
+ # @return [JWT::Configuration::Container] the configuration container.
11
19
  def configuration
12
20
  @configuration ||= ::JWT::Configuration::Container.new
13
21
  end