jwt 2.7.1 → 2.10.3

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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +157 -27
  3. data/README.md +207 -101
  4. data/lib/jwt/base64.rb +19 -2
  5. data/lib/jwt/claims/audience.rb +30 -0
  6. data/lib/jwt/claims/crit.rb +35 -0
  7. data/lib/jwt/claims/decode_verifier.rb +40 -0
  8. data/lib/jwt/claims/expiration.rb +32 -0
  9. data/lib/jwt/claims/issued_at.rb +22 -0
  10. data/lib/jwt/claims/issuer.rb +34 -0
  11. data/lib/jwt/claims/jwt_id.rb +35 -0
  12. data/lib/jwt/claims/not_before.rb +32 -0
  13. data/lib/jwt/claims/numeric.rb +77 -0
  14. data/lib/jwt/claims/required.rb +33 -0
  15. data/lib/jwt/claims/subject.rb +30 -0
  16. data/lib/jwt/claims/verification_methods.rb +20 -0
  17. data/lib/jwt/claims/verifier.rb +61 -0
  18. data/lib/jwt/claims.rb +74 -0
  19. data/lib/jwt/claims_validator.rb +6 -25
  20. data/lib/jwt/configuration/container.rb +34 -3
  21. data/lib/jwt/configuration/decode_configuration.rb +24 -0
  22. data/lib/jwt/configuration/jwk_configuration.rb +2 -1
  23. data/lib/jwt/configuration.rb +8 -0
  24. data/lib/jwt/decode.rb +34 -82
  25. data/lib/jwt/deprecations.rb +49 -0
  26. data/lib/jwt/encode.rb +18 -67
  27. data/lib/jwt/encoded_token.rb +139 -0
  28. data/lib/jwt/error.rb +35 -0
  29. data/lib/jwt/json.rb +1 -1
  30. data/lib/jwt/jwa/compat.rb +32 -0
  31. data/lib/jwt/{algos → jwa}/ecdsa.rb +40 -26
  32. data/lib/jwt/jwa/eddsa.rb +35 -0
  33. data/lib/jwt/{algos → jwa}/hmac.rb +31 -20
  34. data/lib/jwt/jwa/hmac_rbnacl.rb +50 -0
  35. data/lib/jwt/jwa/hmac_rbnacl_fixed.rb +47 -0
  36. data/lib/jwt/jwa/none.rb +24 -0
  37. data/lib/jwt/jwa/ps.rb +35 -0
  38. data/lib/jwt/jwa/rsa.rb +35 -0
  39. data/lib/jwt/jwa/signing_algorithm.rb +63 -0
  40. data/lib/jwt/jwa/unsupported.rb +20 -0
  41. data/lib/jwt/jwa/wrapper.rb +44 -0
  42. data/lib/jwt/jwa.rb +58 -0
  43. data/lib/jwt/jwk/ec.rb +44 -30
  44. data/lib/jwt/jwk/hmac.rb +2 -3
  45. data/lib/jwt/jwk/key_base.rb +4 -1
  46. data/lib/jwt/jwk/key_finder.rb +5 -4
  47. data/lib/jwt/jwk/kid_as_key_digest.rb +1 -0
  48. data/lib/jwt/jwk/okp_rbnacl.rb +3 -4
  49. data/lib/jwt/jwk/rsa.rb +2 -3
  50. data/lib/jwt/jwk/set.rb +3 -1
  51. data/lib/jwt/jwk.rb +2 -1
  52. data/lib/jwt/token.rb +112 -0
  53. data/lib/jwt/verify.rb +16 -89
  54. data/lib/jwt/version.rb +33 -11
  55. data/lib/jwt/x5c_key_finder.rb +2 -5
  56. data/lib/jwt.rb +24 -1
  57. data/ruby-jwt.gemspec +4 -0
  58. metadata +76 -18
  59. data/lib/jwt/algos/algo_wrapper.rb +0 -26
  60. data/lib/jwt/algos/eddsa.rb +0 -33
  61. data/lib/jwt/algos/hmac_rbnacl.rb +0 -53
  62. data/lib/jwt/algos/hmac_rbnacl_fixed.rb +0 -52
  63. data/lib/jwt/algos/none.rb +0 -19
  64. data/lib/jwt/algos/ps.rb +0 -41
  65. data/lib/jwt/algos/rsa.rb +0 -23
  66. data/lib/jwt/algos/unsupported.rb +0 -19
  67. data/lib/jwt/algos.rb +0 -66
metadata CHANGED
@@ -1,15 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jwt
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.7.1
4
+ version: 2.10.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Rudat
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-06-09 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: base64
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
13
26
  - !ruby/object:Gem::Dependency
14
27
  name: appraisal
15
28
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +51,20 @@ dependencies:
38
51
  - - ">="
39
52
  - !ruby/object:Gem::Version
40
53
  version: '0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: logger
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
41
68
  - !ruby/object:Gem::Dependency
42
69
  name: rake
43
70
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +93,20 @@ dependencies:
66
93
  - - ">="
67
94
  - !ruby/object:Gem::Version
68
95
  version: '0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: rubocop
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
69
110
  - !ruby/object:Gem::Dependency
70
111
  name: simplecov
71
112
  requirement: !ruby/object:Gem::Requirement
@@ -94,27 +135,45 @@ files:
94
135
  - LICENSE
95
136
  - README.md
96
137
  - lib/jwt.rb
97
- - lib/jwt/algos.rb
98
- - lib/jwt/algos/algo_wrapper.rb
99
- - lib/jwt/algos/ecdsa.rb
100
- - lib/jwt/algos/eddsa.rb
101
- - lib/jwt/algos/hmac.rb
102
- - lib/jwt/algos/hmac_rbnacl.rb
103
- - lib/jwt/algos/hmac_rbnacl_fixed.rb
104
- - lib/jwt/algos/none.rb
105
- - lib/jwt/algos/ps.rb
106
- - lib/jwt/algos/rsa.rb
107
- - lib/jwt/algos/unsupported.rb
108
138
  - lib/jwt/base64.rb
139
+ - lib/jwt/claims.rb
140
+ - lib/jwt/claims/audience.rb
141
+ - lib/jwt/claims/crit.rb
142
+ - lib/jwt/claims/decode_verifier.rb
143
+ - lib/jwt/claims/expiration.rb
144
+ - lib/jwt/claims/issued_at.rb
145
+ - lib/jwt/claims/issuer.rb
146
+ - lib/jwt/claims/jwt_id.rb
147
+ - lib/jwt/claims/not_before.rb
148
+ - lib/jwt/claims/numeric.rb
149
+ - lib/jwt/claims/required.rb
150
+ - lib/jwt/claims/subject.rb
151
+ - lib/jwt/claims/verification_methods.rb
152
+ - lib/jwt/claims/verifier.rb
109
153
  - lib/jwt/claims_validator.rb
110
154
  - lib/jwt/configuration.rb
111
155
  - lib/jwt/configuration/container.rb
112
156
  - lib/jwt/configuration/decode_configuration.rb
113
157
  - lib/jwt/configuration/jwk_configuration.rb
114
158
  - lib/jwt/decode.rb
159
+ - lib/jwt/deprecations.rb
115
160
  - lib/jwt/encode.rb
161
+ - lib/jwt/encoded_token.rb
116
162
  - lib/jwt/error.rb
117
163
  - lib/jwt/json.rb
164
+ - lib/jwt/jwa.rb
165
+ - lib/jwt/jwa/compat.rb
166
+ - lib/jwt/jwa/ecdsa.rb
167
+ - lib/jwt/jwa/eddsa.rb
168
+ - lib/jwt/jwa/hmac.rb
169
+ - lib/jwt/jwa/hmac_rbnacl.rb
170
+ - lib/jwt/jwa/hmac_rbnacl_fixed.rb
171
+ - lib/jwt/jwa/none.rb
172
+ - lib/jwt/jwa/ps.rb
173
+ - lib/jwt/jwa/rsa.rb
174
+ - lib/jwt/jwa/signing_algorithm.rb
175
+ - lib/jwt/jwa/unsupported.rb
176
+ - lib/jwt/jwa/wrapper.rb
118
177
  - lib/jwt/jwk.rb
119
178
  - lib/jwt/jwk/ec.rb
120
179
  - lib/jwt/jwk/hmac.rb
@@ -125,6 +184,7 @@ files:
125
184
  - lib/jwt/jwk/rsa.rb
126
185
  - lib/jwt/jwk/set.rb
127
186
  - lib/jwt/jwk/thumbprint.rb
187
+ - lib/jwt/token.rb
128
188
  - lib/jwt/verify.rb
129
189
  - lib/jwt/version.rb
130
190
  - lib/jwt/x5c_key_finder.rb
@@ -134,9 +194,8 @@ licenses:
134
194
  - MIT
135
195
  metadata:
136
196
  bug_tracker_uri: https://github.com/jwt/ruby-jwt/issues
137
- changelog_uri: https://github.com/jwt/ruby-jwt/blob/v2.7.1/CHANGELOG.md
197
+ changelog_uri: https://github.com/jwt/ruby-jwt/blob/v2.10.3/CHANGELOG.md
138
198
  rubygems_mfa_required: 'true'
139
- post_install_message:
140
199
  rdoc_options: []
141
200
  require_paths:
142
201
  - lib
@@ -151,8 +210,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
151
210
  - !ruby/object:Gem::Version
152
211
  version: '0'
153
212
  requirements: []
154
- rubygems_version: 3.3.7
155
- signing_key:
213
+ rubygems_version: 4.0.10
156
214
  specification_version: 4
157
215
  summary: JSON Web Token implementation in Ruby
158
216
  test_files: []
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JWT
4
- module Algos
5
- class AlgoWrapper
6
- attr_reader :alg, :cls
7
-
8
- def initialize(alg, cls)
9
- @alg = alg
10
- @cls = cls
11
- end
12
-
13
- def valid_alg?(alg_to_check)
14
- alg&.casecmp(alg_to_check)&.zero? == true
15
- end
16
-
17
- def sign(data:, signing_key:)
18
- cls.sign(alg, data, signing_key)
19
- end
20
-
21
- def verify(data:, signature:, verification_key:)
22
- cls.verify(alg, verification_key, data, signature)
23
- end
24
- end
25
- end
26
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JWT
4
- module Algos
5
- module Eddsa
6
- module_function
7
-
8
- SUPPORTED = %w[ED25519 EdDSA].freeze
9
-
10
- def sign(algorithm, msg, key)
11
- if key.class != RbNaCl::Signatures::Ed25519::SigningKey
12
- raise EncodeError, "Key given is a #{key.class} but has to be an RbNaCl::Signatures::Ed25519::SigningKey"
13
- end
14
- unless SUPPORTED.map(&:downcase).map(&:to_sym).include?(algorithm.downcase.to_sym)
15
- raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key.primitive} signing key was provided"
16
- end
17
-
18
- key.sign(msg)
19
- end
20
-
21
- def verify(algorithm, public_key, signing_input, signature)
22
- unless SUPPORTED.map(&:downcase).map(&:to_sym).include?(algorithm.downcase.to_sym)
23
- raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key.primitive} signing key was provided"
24
- end
25
- raise DecodeError, "key given is a #{public_key.class} but has to be a RbNaCl::Signatures::Ed25519::VerifyKey" if public_key.class != RbNaCl::Signatures::Ed25519::VerifyKey
26
-
27
- public_key.verify(signature, signing_input)
28
- rescue RbNaCl::CryptoError
29
- false
30
- end
31
- end
32
- end
33
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JWT
4
- module Algos
5
- module HmacRbNaCl
6
- module_function
7
-
8
- MAPPING = {
9
- 'HS256' => ::RbNaCl::HMAC::SHA256,
10
- 'HS512256' => ::RbNaCl::HMAC::SHA512256,
11
- 'HS384' => nil,
12
- 'HS512' => ::RbNaCl::HMAC::SHA512
13
- }.freeze
14
-
15
- SUPPORTED = MAPPING.keys
16
-
17
- def sign(algorithm, msg, key)
18
- if (hmac = resolve_algorithm(algorithm))
19
- hmac.auth(key_for_rbnacl(hmac, key).encode('binary'), msg.encode('binary'))
20
- else
21
- Hmac.sign(algorithm, msg, key)
22
- end
23
- end
24
-
25
- def verify(algorithm, key, signing_input, signature)
26
- if (hmac = resolve_algorithm(algorithm))
27
- hmac.verify(key_for_rbnacl(hmac, key).encode('binary'), signature.encode('binary'), signing_input.encode('binary'))
28
- else
29
- Hmac.verify(algorithm, key, signing_input, signature)
30
- end
31
- rescue ::RbNaCl::BadAuthenticatorError, ::RbNaCl::LengthError
32
- false
33
- end
34
-
35
- def key_for_rbnacl(hmac, key)
36
- key ||= ''
37
- raise JWT::DecodeError, 'HMAC key expected to be a String' unless key.is_a?(String)
38
-
39
- return padded_empty_key(hmac.key_bytes) if key == ''
40
-
41
- key
42
- end
43
-
44
- def resolve_algorithm(algorithm)
45
- MAPPING.fetch(algorithm)
46
- end
47
-
48
- def padded_empty_key(length)
49
- Array.new(length, 0x0).pack('C*').encode('binary')
50
- end
51
- end
52
- end
53
- end
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JWT
4
- module Algos
5
- module HmacRbNaClFixed
6
- module_function
7
-
8
- MAPPING = {
9
- 'HS256' => ::RbNaCl::HMAC::SHA256,
10
- 'HS512256' => ::RbNaCl::HMAC::SHA512256,
11
- 'HS384' => nil,
12
- 'HS512' => ::RbNaCl::HMAC::SHA512
13
- }.freeze
14
-
15
- SUPPORTED = MAPPING.keys
16
-
17
- def sign(algorithm, msg, key)
18
- key ||= ''
19
-
20
- raise JWT::DecodeError, 'HMAC key expected to be a String' unless key.is_a?(String)
21
-
22
- if (hmac = resolve_algorithm(algorithm)) && key.bytesize <= hmac.key_bytes
23
- hmac.auth(padded_key_bytes(key, hmac.key_bytes), msg.encode('binary'))
24
- else
25
- Hmac.sign(algorithm, msg, key)
26
- end
27
- end
28
-
29
- def verify(algorithm, key, signing_input, signature)
30
- key ||= ''
31
-
32
- raise JWT::DecodeError, 'HMAC key expected to be a String' unless key.is_a?(String)
33
-
34
- if (hmac = resolve_algorithm(algorithm)) && key.bytesize <= hmac.key_bytes
35
- hmac.verify(padded_key_bytes(key, hmac.key_bytes), signature.encode('binary'), signing_input.encode('binary'))
36
- else
37
- Hmac.verify(algorithm, key, signing_input, signature)
38
- end
39
- rescue ::RbNaCl::BadAuthenticatorError, ::RbNaCl::LengthError
40
- false
41
- end
42
-
43
- def resolve_algorithm(algorithm)
44
- MAPPING.fetch(algorithm)
45
- end
46
-
47
- def padded_key_bytes(key, bytesize)
48
- key.bytes.fill(0, key.bytesize...bytesize).pack('C*')
49
- end
50
- end
51
- end
52
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JWT
4
- module Algos
5
- module None
6
- module_function
7
-
8
- SUPPORTED = %w[none].freeze
9
-
10
- def sign(*)
11
- ''
12
- end
13
-
14
- def verify(*)
15
- true
16
- end
17
- end
18
- end
19
- end
data/lib/jwt/algos/ps.rb DELETED
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JWT
4
- module Algos
5
- module Ps
6
- # RSASSA-PSS signing algorithms
7
-
8
- module_function
9
-
10
- SUPPORTED = %w[PS256 PS384 PS512].freeze
11
-
12
- def sign(algorithm, msg, key)
13
- require_openssl!
14
-
15
- raise EncodeError, "The given key is a #{key_class}. It has to be an OpenSSL::PKey::RSA instance." if key.is_a?(String)
16
-
17
- translated_algorithm = algorithm.sub('PS', 'sha')
18
-
19
- key.sign_pss(translated_algorithm, msg, salt_length: :digest, mgf1_hash: translated_algorithm)
20
- end
21
-
22
- def verify(algorithm, public_key, signing_input, signature)
23
- require_openssl!
24
- translated_algorithm = algorithm.sub('PS', 'sha')
25
- public_key.verify_pss(translated_algorithm, signature, signing_input, salt_length: :auto, mgf1_hash: translated_algorithm)
26
- rescue OpenSSL::PKey::PKeyError
27
- raise JWT::VerificationError, 'Signature verification raised'
28
- end
29
-
30
- def require_openssl!
31
- if Object.const_defined?('OpenSSL')
32
- if ::Gem::Version.new(OpenSSL::VERSION) < ::Gem::Version.new('2.1')
33
- raise JWT::RequiredDependencyError, "You currently have OpenSSL #{OpenSSL::VERSION}. PS support requires >= 2.1"
34
- end
35
- else
36
- raise JWT::RequiredDependencyError, 'PS signing requires OpenSSL +2.1'
37
- end
38
- end
39
- end
40
- end
41
- end
data/lib/jwt/algos/rsa.rb DELETED
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JWT
4
- module Algos
5
- module Rsa
6
- module_function
7
-
8
- SUPPORTED = %w[RS256 RS384 RS512].freeze
9
-
10
- def sign(algorithm, msg, key)
11
- raise EncodeError, "The given key is a #{key.class}. It has to be an OpenSSL::PKey::RSA instance." if key.instance_of?(String)
12
-
13
- key.sign(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), msg)
14
- end
15
-
16
- def verify(algorithm, public_key, signing_input, signature)
17
- public_key.verify(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), signature, signing_input)
18
- rescue OpenSSL::PKey::PKeyError
19
- raise JWT::VerificationError, 'Signature verification raised'
20
- end
21
- end
22
- end
23
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JWT
4
- module Algos
5
- module Unsupported
6
- module_function
7
-
8
- SUPPORTED = [].freeze
9
-
10
- def sign(*)
11
- raise NotImplementedError, 'Unsupported signing method'
12
- end
13
-
14
- def verify(*)
15
- raise JWT::VerificationError, 'Algorithm not supported'
16
- end
17
- end
18
- end
19
- end
data/lib/jwt/algos.rb DELETED
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- begin
4
- require 'rbnacl'
5
- rescue LoadError
6
- raise if defined?(RbNaCl)
7
- end
8
- require 'openssl'
9
-
10
- require 'jwt/algos/hmac'
11
- require 'jwt/algos/eddsa'
12
- require 'jwt/algos/ecdsa'
13
- require 'jwt/algos/rsa'
14
- require 'jwt/algos/ps'
15
- require 'jwt/algos/none'
16
- require 'jwt/algos/unsupported'
17
- require 'jwt/algos/algo_wrapper'
18
-
19
- module JWT
20
- module Algos
21
- extend self
22
-
23
- ALGOS = [Algos::Ecdsa,
24
- Algos::Rsa,
25
- Algos::Eddsa,
26
- Algos::Ps,
27
- Algos::None,
28
- Algos::Unsupported].tap do |l|
29
- if ::JWT.rbnacl_6_or_greater?
30
- require_relative 'algos/hmac_rbnacl'
31
- l.unshift(Algos::HmacRbNaCl)
32
- elsif ::JWT.rbnacl?
33
- require_relative 'algos/hmac_rbnacl_fixed'
34
- l.unshift(Algos::HmacRbNaClFixed)
35
- else
36
- l.unshift(Algos::Hmac)
37
- end
38
- end.freeze
39
-
40
- def find(algorithm)
41
- indexed[algorithm && algorithm.downcase]
42
- end
43
-
44
- def create(algorithm)
45
- Algos::AlgoWrapper.new(*find(algorithm))
46
- end
47
-
48
- def implementation?(algorithm)
49
- (algorithm.respond_to?(:valid_alg?) && algorithm.respond_to?(:verify)) ||
50
- (algorithm.respond_to?(:alg) && algorithm.respond_to?(:sign))
51
- end
52
-
53
- private
54
-
55
- def indexed
56
- @indexed ||= begin
57
- fallback = [nil, Algos::Unsupported]
58
- ALGOS.each_with_object(Hash.new(fallback)) do |cls, hash|
59
- cls.const_get(:SUPPORTED).each do |alg|
60
- hash[alg.downcase] = [alg, cls]
61
- end
62
- end
63
- end
64
- end
65
- end
66
- end