jwt 2.8.1 → 2.9.0

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.
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/version.rb CHANGED
@@ -11,9 +11,9 @@ module JWT
11
11
  # major version
12
12
  MAJOR = 2
13
13
  # minor version
14
- MINOR = 8
14
+ MINOR = 9
15
15
  # tiny version
16
- TINY = 1
16
+ TINY = 0
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
@@ -9,6 +9,7 @@ require 'jwt/deprecations'
9
9
  require 'jwt/encode'
10
10
  require 'jwt/error'
11
11
  require 'jwt/jwk'
12
+ require 'jwt/claims'
12
13
 
13
14
  # JSON Web Token implementation
14
15
  #
@@ -27,6 +28,8 @@ module JWT
27
28
  end
28
29
 
29
30
  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
31
+ Deprecations.context do
32
+ Decode.new(jwt, key, verify, configuration.decode.to_h.merge(options), &keyfinder).decode_segments
33
+ end
31
34
  end
32
35
  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.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Rudat
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-29 00:00:00.000000000 Z
11
+ date: 2024-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -123,7 +123,16 @@ files:
123
123
  - README.md
124
124
  - lib/jwt.rb
125
125
  - lib/jwt/base64.rb
126
- - lib/jwt/claims_validator.rb
126
+ - lib/jwt/claims.rb
127
+ - lib/jwt/claims/audience.rb
128
+ - lib/jwt/claims/expiration.rb
129
+ - lib/jwt/claims/issued_at.rb
130
+ - lib/jwt/claims/issuer.rb
131
+ - lib/jwt/claims/jwt_id.rb
132
+ - lib/jwt/claims/not_before.rb
133
+ - lib/jwt/claims/numeric.rb
134
+ - lib/jwt/claims/required.rb
135
+ - lib/jwt/claims/subject.rb
127
136
  - lib/jwt/configuration.rb
128
137
  - lib/jwt/configuration/container.rb
129
138
  - lib/jwt/configuration/decode_configuration.rb
@@ -142,6 +151,7 @@ files:
142
151
  - lib/jwt/jwa/none.rb
143
152
  - lib/jwt/jwa/ps.rb
144
153
  - lib/jwt/jwa/rsa.rb
154
+ - lib/jwt/jwa/signing_algorithm.rb
145
155
  - lib/jwt/jwa/unsupported.rb
146
156
  - lib/jwt/jwa/wrapper.rb
147
157
  - lib/jwt/jwk.rb
@@ -154,7 +164,6 @@ files:
154
164
  - lib/jwt/jwk/rsa.rb
155
165
  - lib/jwt/jwk/set.rb
156
166
  - lib/jwt/jwk/thumbprint.rb
157
- - lib/jwt/verify.rb
158
167
  - lib/jwt/version.rb
159
168
  - lib/jwt/x5c_key_finder.rb
160
169
  - ruby-jwt.gemspec
@@ -163,9 +172,9 @@ licenses:
163
172
  - MIT
164
173
  metadata:
165
174
  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
175
+ changelog_uri: https://github.com/jwt/ruby-jwt/blob/v2.9.0/CHANGELOG.md
167
176
  rubygems_mfa_required: 'true'
168
- post_install_message:
177
+ post_install_message:
169
178
  rdoc_options: []
170
179
  require_paths:
171
180
  - lib
@@ -180,8 +189,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
180
189
  - !ruby/object:Gem::Version
181
190
  version: '0'
182
191
  requirements: []
183
- rubygems_version: 3.3.7
184
- signing_key:
192
+ rubygems_version: 3.5.16
193
+ signing_key:
185
194
  specification_version: 4
186
195
  summary: JSON Web Token implementation in Ruby
187
196
  test_files: []
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'error'
4
-
5
- module JWT
6
- class ClaimsValidator
7
- NUMERIC_CLAIMS = %i[
8
- exp
9
- iat
10
- nbf
11
- ].freeze
12
-
13
- def initialize(payload)
14
- @payload = payload.transform_keys(&:to_sym)
15
- end
16
-
17
- def validate!
18
- validate_numeric_claims
19
-
20
- true
21
- end
22
-
23
- private
24
-
25
- def validate_numeric_claims
26
- NUMERIC_CLAIMS.each do |claim|
27
- validate_is_numeric(claim) if @payload.key?(claim)
28
- end
29
- end
30
-
31
- def validate_is_numeric(claim)
32
- return if @payload[claim].is_a?(Numeric)
33
-
34
- raise InvalidPayload, "#{claim} claim must be a Numeric value but it is a #{@payload[claim].class}"
35
- end
36
- end
37
- end
data/lib/jwt/verify.rb DELETED
@@ -1,117 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'jwt/error'
4
-
5
- module JWT
6
- # JWT verify methods
7
- class Verify
8
- DEFAULTS = {
9
- leeway: 0
10
- }.freeze
11
-
12
- class << self
13
- %w[verify_aud verify_expiration verify_iat verify_iss verify_jti verify_not_before verify_sub verify_required_claims].each do |method_name|
14
- define_method method_name do |payload, options|
15
- new(payload, options).send(method_name)
16
- end
17
- end
18
-
19
- def verify_claims(payload, options)
20
- options.each do |key, val|
21
- next unless key.to_s =~ /verify/
22
-
23
- Verify.send(key, payload, options) if val
24
- end
25
- end
26
- end
27
-
28
- def initialize(payload, options)
29
- @payload = payload
30
- @options = DEFAULTS.merge(options)
31
- end
32
-
33
- def verify_aud
34
- return unless (options_aud = @options[:aud])
35
-
36
- aud = @payload['aud']
37
- raise(JWT::InvalidAudError, "Invalid audience. Expected #{options_aud}, received #{aud || '<none>'}") if ([*aud] & [*options_aud]).empty?
38
- end
39
-
40
- def verify_expiration
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)
43
- end
44
-
45
- def verify_iat
46
- return unless contains_key?(@payload, 'iat')
47
-
48
- iat = @payload['iat']
49
- raise(JWT::InvalidIatError, 'Invalid iat') if !iat.is_a?(Numeric) || iat.to_f > Time.now.to_f
50
- end
51
-
52
- def verify_iss
53
- return unless (options_iss = @options[:iss])
54
-
55
- iss = @payload['iss']
56
-
57
- options_iss = Array(options_iss).map { |item| item.is_a?(Symbol) ? item.to_s : item }
58
-
59
- case iss
60
- when *options_iss
61
- nil
62
- else
63
- raise(JWT::InvalidIssuerError, "Invalid issuer. Expected #{options_iss}, received #{iss || '<none>'}")
64
- end
65
- end
66
-
67
- def verify_jti
68
- options_verify_jti = @options[:verify_jti]
69
- jti = @payload['jti']
70
-
71
- if options_verify_jti.respond_to?(:call)
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
74
- elsif jti.to_s.strip.empty?
75
- raise(JWT::InvalidJtiError, 'Missing jti')
76
- end
77
- end
78
-
79
- def verify_not_before
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)
82
- end
83
-
84
- def verify_sub
85
- return unless (options_sub = @options[:sub])
86
-
87
- sub = @payload['sub']
88
- raise(JWT::InvalidSubError, "Invalid subject. Expected #{options_sub}, received #{sub || '<none>'}") unless sub.to_s == options_sub.to_s
89
- end
90
-
91
- def verify_required_claims
92
- return unless (options_required_claims = @options[:required_claims])
93
-
94
- options_required_claims.each do |required_claim|
95
- raise(JWT::MissingRequiredClaim, "Missing required claim #{required_claim}") unless contains_key?(@payload, required_claim)
96
- end
97
- end
98
-
99
- private
100
-
101
- def global_leeway
102
- @options[:leeway]
103
- end
104
-
105
- def exp_leeway
106
- @options[:exp_leeway] || global_leeway
107
- end
108
-
109
- def nbf_leeway
110
- @options[:nbf_leeway] || global_leeway
111
- end
112
-
113
- def contains_key?(payload, key)
114
- payload.respond_to?(:key?) && payload.key?(key)
115
- end
116
- end
117
- end