jwt 3.1.0 → 3.1.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 +17 -0
- data/README.md +2 -2
- data/lib/jwt/encoded_token.rb +1 -1
- data/lib/jwt/jwa/ecdsa.rb +3 -3
- data/lib/jwt/jwa/rsa.rb +3 -3
- data/lib/jwt/jwa.rb +26 -5
- data/lib/jwt/jwk/ec.rb +2 -2
- data/lib/jwt/jwk/key_base.rb +3 -8
- data/lib/jwt/token.rb +2 -2
- data/lib/jwt/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4fbf6e518cee3ac505360ea356f34fab6a68c5dfc2112671105085fbb03c08df
|
4
|
+
data.tar.gz: 0f206bdf51b4a979b6f734d6582f7e18762f2d3a1ee7feb38499fc4a92d77115
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4fa9df3dae62f1abbe065fd144641a8869faddd45be94cb58871dc690fead80f38f741b5de5319b5a31d8d28fe16ae32627f27d396cbe2f91f80acc9a6d3e477
|
7
|
+
data.tar.gz: 41e30090c5ee55b3706b4d2bddd73dc596e4db46669c292af56bca9ebe9f36a8eafe7ce33578f3012d87f910a6880ee26e6c26c46bfda59470a23f24e47a739d
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [v3.1.2](https://github.com/jwt/ruby-jwt/tree/v3.1.2) (2025-06-28)
|
4
|
+
|
5
|
+
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/v3.1.1...v3.1.2)
|
6
|
+
|
7
|
+
**Fixes and enhancements:**
|
8
|
+
|
9
|
+
- Avoid using the same digest across calls in JWT::JWA::Ecdsa and JWT::JWA::Rsa [#697](https://github.com/jwt/ruby-jwt/pull/697)
|
10
|
+
- Fix signing with a EC JWK [#699](https://github.com/jwt/ruby-jwt/pull/699) ([@anakinj](https://github.com/anakinj))
|
11
|
+
|
12
|
+
## [v3.1.1](https://github.com/jwt/ruby-jwt/tree/v3.1.1) (2025-06-24)
|
13
|
+
|
14
|
+
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/v3.1.0...v3.1.1)
|
15
|
+
|
16
|
+
**Fixes and enhancements:**
|
17
|
+
|
18
|
+
- Require the algorithm to be provided when signing and verifying tokens using JWKs [#695](https://github.com/jwt/ruby-jwt/pull/695) ([@anakinj](https://github.com/anakinj))
|
19
|
+
|
3
20
|
## [v3.1.0](https://github.com/jwt/ruby-jwt/tree/v3.1.0) (2025-06-23)
|
4
21
|
|
5
22
|
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/v3.0.0...v3.1.0)
|
data/README.md
CHANGED
@@ -265,10 +265,10 @@ jwk = JWT::JWK.import(JSON.parse(jwk_json))
|
|
265
265
|
|
266
266
|
token = JWT::Token.new(payload: payload, header: header)
|
267
267
|
|
268
|
-
token.sign!(key: jwk)
|
268
|
+
token.sign!(key: jwk, algorithm: 'HS256')
|
269
269
|
|
270
270
|
encoded_token = JWT::EncodedToken.new(token.jwt)
|
271
|
-
encoded_token.verify!(signature: { key: jwk})
|
271
|
+
encoded_token.verify!(signature: { algorithm: ["HS256", "HS512"], key: jwk})
|
272
272
|
```
|
273
273
|
|
274
274
|
#### Using a keyfinder
|
data/lib/jwt/encoded_token.rb
CHANGED
@@ -138,7 +138,7 @@ module JWT
|
|
138
138
|
# @return [nil]
|
139
139
|
# @raise [JWT::VerificationError] if the signature verification fails.
|
140
140
|
# @raise [ArgumentError] if neither key nor key_finder is provided, or if both are provided.
|
141
|
-
def verify_signature!(algorithm
|
141
|
+
def verify_signature!(algorithm:, key: nil, key_finder: nil)
|
142
142
|
return if valid_signature?(algorithm: algorithm, key: key, key_finder: key_finder)
|
143
143
|
|
144
144
|
raise JWT::VerificationError, 'Signature verification failed'
|
data/lib/jwt/jwa/ecdsa.rb
CHANGED
@@ -8,7 +8,7 @@ module JWT
|
|
8
8
|
|
9
9
|
def initialize(alg, digest)
|
10
10
|
@alg = alg
|
11
|
-
@digest =
|
11
|
+
@digest = digest
|
12
12
|
end
|
13
13
|
|
14
14
|
def sign(data:, signing_key:)
|
@@ -20,7 +20,7 @@ module JWT
|
|
20
20
|
|
21
21
|
raise IncorrectAlgorithm, "payload algorithm is #{alg} but #{key_algorithm} signing key was provided" if alg != key_algorithm
|
22
22
|
|
23
|
-
asn1_to_raw(signing_key.dsa_sign_asn1(digest.digest(data)), signing_key)
|
23
|
+
asn1_to_raw(signing_key.dsa_sign_asn1(OpenSSL::Digest.new(digest).digest(data)), signing_key)
|
24
24
|
end
|
25
25
|
|
26
26
|
def verify(data:, signature:, verification_key:)
|
@@ -32,7 +32,7 @@ module JWT
|
|
32
32
|
key_algorithm = curve_definition[:algorithm]
|
33
33
|
raise IncorrectAlgorithm, "payload algorithm is #{alg} but #{key_algorithm} verification key was provided" if alg != key_algorithm
|
34
34
|
|
35
|
-
verification_key.dsa_verify_asn1(digest.digest(data), raw_to_asn1(signature, verification_key))
|
35
|
+
verification_key.dsa_verify_asn1(OpenSSL::Digest.new(digest).digest(data), raw_to_asn1(signature, verification_key))
|
36
36
|
rescue OpenSSL::PKey::PKeyError
|
37
37
|
raise JWT::VerificationError, 'Signature verification raised'
|
38
38
|
end
|
data/lib/jwt/jwa/rsa.rb
CHANGED
@@ -8,18 +8,18 @@ module JWT
|
|
8
8
|
|
9
9
|
def initialize(alg)
|
10
10
|
@alg = alg
|
11
|
-
@digest =
|
11
|
+
@digest = alg.sub('RS', 'SHA')
|
12
12
|
end
|
13
13
|
|
14
14
|
def sign(data:, signing_key:)
|
15
15
|
raise_sign_error!("The given key is a #{signing_key.class}. It has to be an OpenSSL::PKey::RSA instance") unless signing_key.is_a?(OpenSSL::PKey::RSA)
|
16
16
|
raise_sign_error!('The key length must be greater than or equal to 2048 bits') if signing_key.n.num_bits < 2048
|
17
17
|
|
18
|
-
signing_key.sign(digest, data)
|
18
|
+
signing_key.sign(OpenSSL::Digest.new(digest), data)
|
19
19
|
end
|
20
20
|
|
21
21
|
def verify(data:, signature:, verification_key:)
|
22
|
-
verification_key.verify(digest, signature, data)
|
22
|
+
verification_key.verify(OpenSSL::Digest.new(digest), signature, data)
|
23
23
|
rescue OpenSSL::PKey::PKeyError
|
24
24
|
raise JWT::VerificationError, 'Signature verification raised'
|
25
25
|
end
|
data/lib/jwt/jwa.rb
CHANGED
@@ -15,6 +15,8 @@ module JWT
|
|
15
15
|
module JWA
|
16
16
|
# @api private
|
17
17
|
class VerifierContext
|
18
|
+
attr_reader :jwa
|
19
|
+
|
18
20
|
def initialize(jwa:, keys:)
|
19
21
|
@jwa = jwa
|
20
22
|
@keys = Array(keys)
|
@@ -29,6 +31,8 @@ module JWT
|
|
29
31
|
|
30
32
|
# @api private
|
31
33
|
class SignerContext
|
34
|
+
attr_reader :jwa
|
35
|
+
|
32
36
|
def initialize(jwa:, key:)
|
33
37
|
@jwa = jwa
|
34
38
|
@key = key
|
@@ -37,10 +41,6 @@ module JWT
|
|
37
41
|
def sign(*args, **kwargs)
|
38
42
|
@jwa.sign(*args, **kwargs, signing_key: @key)
|
39
43
|
end
|
40
|
-
|
41
|
-
def jwa_header
|
42
|
-
@jwa.header
|
43
|
-
end
|
44
44
|
end
|
45
45
|
|
46
46
|
class << self
|
@@ -64,7 +64,11 @@ module JWT
|
|
64
64
|
|
65
65
|
# @api private
|
66
66
|
def create_signer(algorithm:, key:)
|
67
|
-
|
67
|
+
if key.is_a?(JWK::KeyBase)
|
68
|
+
validate_jwk_algorithms!(key, algorithm, DecodeError)
|
69
|
+
|
70
|
+
return key
|
71
|
+
end
|
68
72
|
|
69
73
|
SignerContext.new(jwa: resolve(algorithm), key: key)
|
70
74
|
end
|
@@ -73,10 +77,27 @@ module JWT
|
|
73
77
|
def create_verifiers(algorithms:, keys:, preferred_algorithm:)
|
74
78
|
jwks, other_keys = keys.partition { |key| key.is_a?(JWK::KeyBase) }
|
75
79
|
|
80
|
+
validate_jwk_algorithms!(jwks, algorithms, VerificationError)
|
81
|
+
|
76
82
|
jwks + resolve_and_sort(algorithms: algorithms,
|
77
83
|
preferred_algorithm: preferred_algorithm)
|
78
84
|
.map { |jwa| VerifierContext.new(jwa: jwa, keys: other_keys) }
|
79
85
|
end
|
86
|
+
|
87
|
+
# @api private
|
88
|
+
def validate_jwk_algorithms!(jwks, algorithms, error_class)
|
89
|
+
algorithms = Array(algorithms)
|
90
|
+
|
91
|
+
return if algorithms.empty?
|
92
|
+
|
93
|
+
return if Array(jwks).all? do |jwk|
|
94
|
+
algorithms.any? do |alg|
|
95
|
+
jwk.jwa.valid_alg?(alg)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
raise error_class, "Provided JWKs do not support one of the specified algorithms: #{algorithms.join(', ')}"
|
100
|
+
end
|
80
101
|
end
|
81
102
|
end
|
82
103
|
end
|
data/lib/jwt/jwk/ec.rb
CHANGED
@@ -71,8 +71,6 @@ module JWT
|
|
71
71
|
super
|
72
72
|
end
|
73
73
|
|
74
|
-
private
|
75
|
-
|
76
74
|
def jwa
|
77
75
|
return super if self[:alg]
|
78
76
|
|
@@ -80,6 +78,8 @@ module JWT
|
|
80
78
|
JWA.resolve(JWA::Ecdsa.curve_by_name(curve_name)[:algorithm])
|
81
79
|
end
|
82
80
|
|
81
|
+
private
|
82
|
+
|
83
83
|
def ec_key
|
84
84
|
@ec_key ||= create_ec_key(self[:crv], self[:x], self[:y], self[:d])
|
85
85
|
end
|
data/lib/jwt/jwk/key_base.rb
CHANGED
@@ -50,11 +50,6 @@ module JWT
|
|
50
50
|
jwa.sign(**kwargs, signing_key: signing_key)
|
51
51
|
end
|
52
52
|
|
53
|
-
# @api private
|
54
|
-
def jwa_header
|
55
|
-
jwa.header
|
56
|
-
end
|
57
|
-
|
58
53
|
alias eql? ==
|
59
54
|
|
60
55
|
def <=>(other)
|
@@ -63,12 +58,12 @@ module JWT
|
|
63
58
|
self[:kid] <=> other[:kid]
|
64
59
|
end
|
65
60
|
|
66
|
-
private
|
67
|
-
|
68
61
|
def jwa
|
69
62
|
raise JWT::JWKError, 'Could not resolve the JWA, the "alg" parameter is missing' unless self[:alg]
|
70
63
|
|
71
|
-
JWA.resolve(self[:alg])
|
64
|
+
JWA.resolve(self[:alg]).tap do |jwa|
|
65
|
+
raise JWT::JWKError, 'none algorithm usage not supported via JWK' if jwa.is_a?(JWA::None)
|
66
|
+
end
|
72
67
|
end
|
73
68
|
|
74
69
|
attr_reader :parameters
|
data/lib/jwt/token.rb
CHANGED
@@ -91,11 +91,11 @@ module JWT
|
|
91
91
|
# @param algorithm [String, Object] the algorithm to use for signing.
|
92
92
|
# @return [void]
|
93
93
|
# @raise [JWT::EncodeError] if the token is already signed or other problems when signing
|
94
|
-
def sign!(key:, algorithm:
|
94
|
+
def sign!(key:, algorithm:)
|
95
95
|
raise ::JWT::EncodeError, 'Token already signed' if @signature
|
96
96
|
|
97
97
|
JWA.create_signer(algorithm: algorithm, key: key).tap do |signer|
|
98
|
-
header.merge!(signer.
|
98
|
+
header.merge!(signer.jwa.header) { |_key, old, _new| old }
|
99
99
|
@signature = signer.sign(data: signing_input)
|
100
100
|
end
|
101
101
|
|
data/lib/jwt/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jwt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1.
|
4
|
+
version: 3.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Rudat
|
@@ -199,7 +199,7 @@ licenses:
|
|
199
199
|
- MIT
|
200
200
|
metadata:
|
201
201
|
bug_tracker_uri: https://github.com/jwt/ruby-jwt/issues
|
202
|
-
changelog_uri: https://github.com/jwt/ruby-jwt/blob/v3.1.
|
202
|
+
changelog_uri: https://github.com/jwt/ruby-jwt/blob/v3.1.2/CHANGELOG.md
|
203
203
|
rubygems_mfa_required: 'true'
|
204
204
|
rdoc_options: []
|
205
205
|
require_paths:
|