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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a9dd430911612a1bef370bffdf46f432a9ec2027f2091efd8d47e6d237d8c935
4
- data.tar.gz: 6fa7001bc60edeb8c984cddef3bf5d9beb42656555593ad8ffc2dfe3ef4b76e8
3
+ metadata.gz: 4fbf6e518cee3ac505360ea356f34fab6a68c5dfc2112671105085fbb03c08df
4
+ data.tar.gz: 0f206bdf51b4a979b6f734d6582f7e18762f2d3a1ee7feb38499fc4a92d77115
5
5
  SHA512:
6
- metadata.gz: 11a6a56acb50a86223e7f60f413ac723c34997bd7ad5f2bbf2376e6c66fbfca1991a08301147062e7d5835f8fd530509b53a80876781d890d52e7fab7389fe18
7
- data.tar.gz: 44f001cb3c746e4fe502a72fa9bc9234066a687145443c14cd4b09ef2bd184d119bf0d99accbfd3cd748e0eb1e8696fd90446cc3be4851ead641adbba9246b7c
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
@@ -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: nil, key: nil, key_finder: nil)
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 = OpenSSL::Digest.new(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 = OpenSSL::Digest.new(alg.sub('RS', 'SHA'))
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
- return key if key.is_a?(JWK::KeyBase)
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
@@ -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: nil)
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.jwa_header) { |_key, old, _new| old }
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
@@ -16,7 +16,7 @@ module JWT
16
16
  module VERSION
17
17
  MAJOR = 3
18
18
  MINOR = 1
19
- TINY = 0
19
+ TINY = 2
20
20
  PRE = nil
21
21
 
22
22
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
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.0
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.0/CHANGELOG.md
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: