jwt 2.8.1 → 2.8.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af3792b982f014801d3ff7ae3410be6bd1e0b27f199c500942eb86267bb2b764
4
- data.tar.gz: c37fc4b72cf3819210b15164548eff44579de1e8f8c48d9ce35864a84f007d9a
3
+ metadata.gz: 5fc1b13d678680a3d1b23e06cad091deb0f3ffff77783a99cd1d1f7231938563
4
+ data.tar.gz: f7d3f5294cb3b6ba57c2772a58c50ee2d55cf6412db6b707a38c74b381662777
5
5
  SHA512:
6
- metadata.gz: 3f61fd13a1d56c657691abb4bfde3671a7d93b5c853785b804c0d119d27f4641685828eb9c65a8e4856487782530e791ecbce5f1a5f1cb61c883daff97a44367
7
- data.tar.gz: ef36aa81991e28cb9d3df65f1ebbeb6599eb99dee8e1953aff1a6231e91c6a3f9633e3afd22fbbc6c09f6318c4e516ee7a908428eee303f3952fed890395b267
6
+ metadata.gz: 5f4602ed313d982db0a2e469c2fc3b58aa0de226f85e332501628d9f7b59ed8a84e78691b57f14ddf153c4be028e9b3caa13d9b3231996c798e9e63f69f4d10a
7
+ data.tar.gz: a3ed20caccfe2c2979426b41a6e0bbeeabe67157643c4571836642f48ccf76ba8f58bb3270501eeefcbd53e1d027de1b558310a083360ca644157934ce3c06bf
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [v2.8.2](https://github.com/jwt/ruby-jwt/tree/v2.8.2) (2024-06-18)
4
+
5
+ [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.8.1...v2.8.2)
6
+
7
+ **Fixes and enhancements:**
8
+
9
+ - Print deprecation warnings only on when token decoding succeeds [#600](https://github.com/jwt/ruby-jwt/pull/600) ([@anakinj](https://github.com/anakinj))
10
+ - Unify code style [#602](https://github.com/jwt/ruby-jwt/pull/602) ([@anakinj](https://github.com/anakinj))
11
+
3
12
  ## [v2.8.1](https://github.com/jwt/ruby-jwt/tree/v2.8.1) (2024-02-29)
4
13
 
5
14
  [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.8.0...v2.8.1)
data/lib/jwt/base64.rb CHANGED
@@ -20,7 +20,7 @@ module JWT
20
20
  raise Base64DecodeError, 'Invalid base64 encoding' if JWT.configuration.strict_base64_decoding
21
21
 
22
22
  loose_urlsafe_decode64(str).tap do
23
- Deprecations.warning('Invalid base64 input detected, could be because of invalid padding, trailing whitespaces or newline chars. Graceful handling of invalid input will be dropped in the next major version of ruby-jwt')
23
+ Deprecations.warning('Invalid base64 input detected, could be because of invalid padding, trailing whitespaces or newline chars. Graceful handling of invalid input will be dropped in the next major version of ruby-jwt', only_if_valid: true)
24
24
  end
25
25
  end
26
26
 
@@ -18,7 +18,7 @@ module JWT
18
18
  JWT::JWK::Thumbprint
19
19
  else
20
20
  raise ArgumentError, "#{value} is not a valid kid generator type."
21
- end
21
+ end
22
22
  end
23
23
 
24
24
  attr_accessor :kid_generator
data/lib/jwt/decode.rb CHANGED
@@ -10,7 +10,7 @@ module JWT
10
10
  # Decoding logic for JWT
11
11
  class Decode
12
12
  def initialize(jwt, key, verify, options, &keyfinder)
13
- raise(JWT::DecodeError, 'Nil JSON web token') unless jwt
13
+ raise JWT::DecodeError, 'Nil JSON web token' unless jwt
14
14
 
15
15
  @jwt = jwt
16
16
  @key = key
@@ -30,7 +30,7 @@ module JWT
30
30
  verify_signature
31
31
  verify_claims
32
32
  end
33
- raise(JWT::DecodeError, 'Not enough or too many segments') unless header && payload
33
+ raise JWT::DecodeError, 'Not enough or too many segments' unless header && payload
34
34
 
35
35
  [payload, header]
36
36
  end
@@ -46,21 +46,21 @@ module JWT
46
46
 
47
47
  return if Array(@key).any? { |key| verify_signature_for?(key) }
48
48
 
49
- raise(JWT::VerificationError, 'Signature verification failed')
49
+ raise JWT::VerificationError, 'Signature verification failed'
50
50
  end
51
51
 
52
52
  def verify_algo
53
- raise(JWT::IncorrectAlgorithm, 'An algorithm must be specified') if allowed_algorithms.empty?
54
- raise(JWT::IncorrectAlgorithm, 'Token is missing alg header') unless alg_in_header
55
- raise(JWT::IncorrectAlgorithm, 'Expected a different algorithm') if allowed_and_valid_algorithms.empty?
53
+ raise JWT::IncorrectAlgorithm, 'An algorithm must be specified' if allowed_algorithms.empty?
54
+ raise JWT::IncorrectAlgorithm, 'Token is missing alg header' unless alg_in_header
55
+ raise JWT::IncorrectAlgorithm, 'Expected a different algorithm' if allowed_and_valid_algorithms.empty?
56
56
  end
57
57
 
58
58
  def set_key
59
59
  @key = find_key(&@keyfinder) if @keyfinder
60
60
  @key = ::JWT::JWK::KeyFinder.new(jwks: @options[:jwks], allow_nil_kid: @options[:allow_nil_kid]).key_for(header['kid']) if @options[:jwks]
61
- if (x5c_options = @options[:x5c])
62
- @key = X5cKeyFinder.new(x5c_options[:root_certificates], x5c_options[:crls]).from(header['x5c'])
63
- end
61
+ return unless (x5c_options = @options[:x5c])
62
+
63
+ @key = X5cKeyFinder.new(x5c_options[:root_certificates], x5c_options[:crls]).from(header['x5c'])
64
64
  end
65
65
 
66
66
  def verify_signature_for?(key)
@@ -122,7 +122,7 @@ module JWT
122
122
  return if !@verify && segment_length == 2 # If no verifying required, the signature is not needed
123
123
  return if segment_length == 2 && none_algorithm?
124
124
 
125
- raise(JWT::DecodeError, 'Not enough or too many segments')
125
+ raise JWT::DecodeError, 'Not enough or too many segments'
126
126
  end
127
127
 
128
128
  def segment_length
@@ -4,15 +4,34 @@ module JWT
4
4
  # Deprecations module to handle deprecation warnings in the gem
5
5
  module Deprecations
6
6
  class << self
7
- def warning(message)
7
+ def context
8
+ yield.tap { emit_warnings }
9
+ ensure
10
+ Thread.current[:jwt_warning_store] = nil
11
+ end
12
+
13
+ def warning(message, only_if_valid: false)
14
+ method_name = only_if_valid ? :store : :warn
8
15
  case JWT.configuration.deprecation_warnings
9
- when :warn
10
- warn("[DEPRECATION WARNING] #{message}")
11
16
  when :once
12
17
  return if record_warned(message)
13
-
14
- warn("[DEPRECATION WARNING] #{message}")
18
+ when :warn
19
+ # noop
20
+ else
21
+ return
15
22
  end
23
+
24
+ send(method_name, "[DEPRECATION WARNING] #{message}")
25
+ end
26
+
27
+ def store(message)
28
+ (Thread.current[:jwt_warning_store] ||= []) << message
29
+ end
30
+
31
+ def emit_warnings
32
+ return if Thread.current[:jwt_warning_store].nil?
33
+
34
+ Thread.current[:jwt_warning_store].each { |warning| warn(warning) }
16
35
  end
17
36
 
18
37
  private
data/lib/jwt/jwk/ec.rb CHANGED
@@ -153,26 +153,26 @@ module JWT
153
153
  )
154
154
 
155
155
  sequence = if jwk_d
156
- # https://datatracker.ietf.org/doc/html/rfc5915.html
157
- # ECPrivateKey ::= SEQUENCE {
158
- # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
159
- # privateKey OCTET STRING,
160
- # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
161
- # publicKey [1] BIT STRING OPTIONAL
162
- # }
163
-
164
- OpenSSL::ASN1::Sequence([
165
- OpenSSL::ASN1::Integer(1),
166
- OpenSSL::ASN1::OctetString(OpenSSL::BN.new(decode_octets(jwk_d), 2).to_s(2)),
167
- OpenSSL::ASN1::ObjectId(curve, 0, :EXPLICIT),
168
- OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed), 1, :EXPLICIT)
169
- ])
170
- else
171
- OpenSSL::ASN1::Sequence([
172
- OpenSSL::ASN1::Sequence([OpenSSL::ASN1::ObjectId('id-ecPublicKey'), OpenSSL::ASN1::ObjectId(curve)]),
173
- OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed))
174
- ])
175
- end
156
+ # https://datatracker.ietf.org/doc/html/rfc5915.html
157
+ # ECPrivateKey ::= SEQUENCE {
158
+ # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
159
+ # privateKey OCTET STRING,
160
+ # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
161
+ # publicKey [1] BIT STRING OPTIONAL
162
+ # }
163
+
164
+ OpenSSL::ASN1::Sequence([
165
+ OpenSSL::ASN1::Integer(1),
166
+ OpenSSL::ASN1::OctetString(OpenSSL::BN.new(decode_octets(jwk_d), 2).to_s(2)),
167
+ OpenSSL::ASN1::ObjectId(curve, 0, :EXPLICIT),
168
+ OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed), 1, :EXPLICIT)
169
+ ])
170
+ else
171
+ OpenSSL::ASN1::Sequence([
172
+ OpenSSL::ASN1::Sequence([OpenSSL::ASN1::ObjectId('id-ecPublicKey'), OpenSSL::ASN1::ObjectId(curve)]),
173
+ OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed))
174
+ ])
175
+ end
176
176
 
177
177
  OpenSSL::PKey::EC.new(sequence.to_der)
178
178
  end
@@ -8,10 +8,10 @@ module JWT
8
8
  jwks_or_loader = options[:jwks]
9
9
 
10
10
  @jwks_loader = if jwks_or_loader.respond_to?(:call)
11
- jwks_or_loader
12
- else
13
- ->(_options) { jwks_or_loader }
14
- end
11
+ jwks_or_loader
12
+ else
13
+ ->(_options) { jwks_or_loader }
14
+ end
15
15
  end
16
16
 
17
17
  def key_for(kid)
data/lib/jwt/jwk/set.rb CHANGED
@@ -25,7 +25,7 @@ module JWT
25
25
  jwks.map { |k| JWT::JWK.new(k, nil, options) }
26
26
  else
27
27
  raise ArgumentError, 'Can only create new JWKS from Hash, Array and JWK'
28
- end
28
+ end
29
29
  end
30
30
 
31
31
  def export(options = {})
data/lib/jwt/verify.rb CHANGED
@@ -34,19 +34,19 @@ module JWT
34
34
  return unless (options_aud = @options[:aud])
35
35
 
36
36
  aud = @payload['aud']
37
- raise(JWT::InvalidAudError, "Invalid audience. Expected #{options_aud}, received #{aud || '<none>'}") if ([*aud] & [*options_aud]).empty?
37
+ raise JWT::InvalidAudError, "Invalid audience. Expected #{options_aud}, received #{aud || '<none>'}" if ([*aud] & [*options_aud]).empty?
38
38
  end
39
39
 
40
40
  def verify_expiration
41
41
  return unless contains_key?(@payload, 'exp')
42
- raise(JWT::ExpiredSignature, 'Signature has expired') if @payload['exp'].to_i <= (Time.now.to_i - exp_leeway)
42
+ raise JWT::ExpiredSignature, 'Signature has expired' if @payload['exp'].to_i <= (Time.now.to_i - exp_leeway)
43
43
  end
44
44
 
45
45
  def verify_iat
46
46
  return unless contains_key?(@payload, 'iat')
47
47
 
48
48
  iat = @payload['iat']
49
- raise(JWT::InvalidIatError, 'Invalid iat') if !iat.is_a?(Numeric) || iat.to_f > Time.now.to_f
49
+ raise JWT::InvalidIatError, 'Invalid iat' if !iat.is_a?(Numeric) || iat.to_f > Time.now.to_f
50
50
  end
51
51
 
52
52
  def verify_iss
@@ -60,7 +60,7 @@ module JWT
60
60
  when *options_iss
61
61
  nil
62
62
  else
63
- raise(JWT::InvalidIssuerError, "Invalid issuer. Expected #{options_iss}, received #{iss || '<none>'}")
63
+ raise JWT::InvalidIssuerError, "Invalid issuer. Expected #{options_iss}, received #{iss || '<none>'}"
64
64
  end
65
65
  end
66
66
 
@@ -70,29 +70,29 @@ module JWT
70
70
 
71
71
  if options_verify_jti.respond_to?(:call)
72
72
  verified = options_verify_jti.arity == 2 ? options_verify_jti.call(jti, @payload) : options_verify_jti.call(jti)
73
- raise(JWT::InvalidJtiError, 'Invalid jti') unless verified
73
+ raise JWT::InvalidJtiError, 'Invalid jti' unless verified
74
74
  elsif jti.to_s.strip.empty?
75
- raise(JWT::InvalidJtiError, 'Missing jti')
75
+ raise JWT::InvalidJtiError, 'Missing jti'
76
76
  end
77
77
  end
78
78
 
79
79
  def verify_not_before
80
80
  return unless contains_key?(@payload, 'nbf')
81
- raise(JWT::ImmatureSignature, 'Signature nbf has not been reached') if @payload['nbf'].to_i > (Time.now.to_i + nbf_leeway)
81
+ raise JWT::ImmatureSignature, 'Signature nbf has not been reached' if @payload['nbf'].to_i > (Time.now.to_i + nbf_leeway)
82
82
  end
83
83
 
84
84
  def verify_sub
85
85
  return unless (options_sub = @options[:sub])
86
86
 
87
87
  sub = @payload['sub']
88
- raise(JWT::InvalidSubError, "Invalid subject. Expected #{options_sub}, received #{sub || '<none>'}") unless sub.to_s == options_sub.to_s
88
+ raise JWT::InvalidSubError, "Invalid subject. Expected #{options_sub}, received #{sub || '<none>'}" unless sub.to_s == options_sub.to_s
89
89
  end
90
90
 
91
91
  def verify_required_claims
92
92
  return unless (options_required_claims = @options[:required_claims])
93
93
 
94
94
  options_required_claims.each do |required_claim|
95
- raise(JWT::MissingRequiredClaim, "Missing required claim #{required_claim}") unless contains_key?(@payload, required_claim)
95
+ raise JWT::MissingRequiredClaim, "Missing required claim #{required_claim}" unless contains_key?(@payload, required_claim)
96
96
  end
97
97
  end
98
98
 
data/lib/jwt/version.rb CHANGED
@@ -13,7 +13,7 @@ module JWT
13
13
  # minor version
14
14
  MINOR = 8
15
15
  # tiny version
16
- TINY = 1
16
+ TINY = 2
17
17
  # alpha, beta, etc. tag
18
18
  PRE = nil
19
19
 
@@ -7,7 +7,7 @@ module JWT
7
7
  # See https://tools.ietf.org/html/rfc7515#section-4.1.6
8
8
  class X5cKeyFinder
9
9
  def initialize(root_certificates, crls = nil)
10
- raise(ArgumentError, 'Root certificates must be specified') unless root_certificates
10
+ raise ArgumentError, 'Root certificates must be specified' unless root_certificates
11
11
 
12
12
  @store = build_store(root_certificates, crls)
13
13
  end
@@ -24,7 +24,7 @@ module JWT
24
24
  error = "#{error} Certificate subject: #{current_cert.subject}."
25
25
  end
26
26
 
27
- raise(JWT::VerificationError, error)
27
+ raise JWT::VerificationError, error
28
28
  end
29
29
  end
30
30
 
data/lib/jwt.rb CHANGED
@@ -27,6 +27,8 @@ module JWT
27
27
  end
28
28
 
29
29
  def decode(jwt, key = nil, verify = true, options = {}, &keyfinder) # rubocop:disable Style/OptionalBooleanParameter
30
- Decode.new(jwt, key, verify, configuration.decode.to_h.merge(options), &keyfinder).decode_segments
30
+ Deprecations.context do
31
+ Decode.new(jwt, key, verify, configuration.decode.to_h.merge(options), &keyfinder).decode_segments
32
+ end
31
33
  end
32
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jwt
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.1
4
+ version: 2.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Rudat
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-29 00:00:00.000000000 Z
11
+ date: 2024-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -163,7 +163,7 @@ licenses:
163
163
  - MIT
164
164
  metadata:
165
165
  bug_tracker_uri: https://github.com/jwt/ruby-jwt/issues
166
- changelog_uri: https://github.com/jwt/ruby-jwt/blob/v2.8.1/CHANGELOG.md
166
+ changelog_uri: https://github.com/jwt/ruby-jwt/blob/v2.8.2/CHANGELOG.md
167
167
  rubygems_mfa_required: 'true'
168
168
  post_install_message:
169
169
  rdoc_options: []
@@ -180,7 +180,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
180
180
  - !ruby/object:Gem::Version
181
181
  version: '0'
182
182
  requirements: []
183
- rubygems_version: 3.3.7
183
+ rubygems_version: 3.5.3
184
184
  signing_key:
185
185
  specification_version: 4
186
186
  summary: JSON Web Token implementation in Ruby