jwt 2.8.1 → 2.8.2

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