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 +4 -4
- data/CHANGELOG.md +9 -0
- data/lib/jwt/base64.rb +1 -1
- data/lib/jwt/configuration/jwk_configuration.rb +1 -1
- data/lib/jwt/decode.rb +10 -10
- data/lib/jwt/deprecations.rb +24 -5
- data/lib/jwt/jwk/ec.rb +20 -20
- data/lib/jwt/jwk/key_finder.rb +4 -4
- data/lib/jwt/jwk/set.rb +1 -1
- data/lib/jwt/verify.rb +9 -9
- data/lib/jwt/version.rb +1 -1
- data/lib/jwt/x5c_key_finder.rb +2 -2
- data/lib/jwt.rb +3 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5fc1b13d678680a3d1b23e06cad091deb0f3ffff77783a99cd1d1f7231938563
|
4
|
+
data.tar.gz: f7d3f5294cb3b6ba57c2772a58c50ee2d55cf6412db6b707a38c74b381662777
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
|
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
|
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
|
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
|
49
|
+
raise JWT::VerificationError, 'Signature verification failed'
|
50
50
|
end
|
51
51
|
|
52
52
|
def verify_algo
|
53
|
-
raise
|
54
|
-
raise
|
55
|
-
raise
|
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
|
-
|
62
|
-
|
63
|
-
|
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
|
125
|
+
raise JWT::DecodeError, 'Not enough or too many segments'
|
126
126
|
end
|
127
127
|
|
128
128
|
def segment_length
|
data/lib/jwt/deprecations.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
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
|
data/lib/jwt/jwk/key_finder.rb
CHANGED
@@ -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
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
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
|
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
|
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
|
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
|
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
|
73
|
+
raise JWT::InvalidJtiError, 'Invalid jti' unless verified
|
74
74
|
elsif jti.to_s.strip.empty?
|
75
|
-
raise
|
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
|
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
|
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
|
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
data/lib/jwt/x5c_key_finder.rb
CHANGED
@@ -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
|
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
|
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
|
-
|
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.
|
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-
|
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.
|
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
|
183
|
+
rubygems_version: 3.5.3
|
184
184
|
signing_key:
|
185
185
|
specification_version: 4
|
186
186
|
summary: JSON Web Token implementation in Ruby
|