jwt 2.9.1 → 2.10.1

Sign up to get free protection for your applications and to get access to all the features.
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