jwt 2.10.1 → 3.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +73 -32
- data/CODE_OF_CONDUCT.md +14 -14
- data/CONTRIBUTING.md +9 -10
- data/README.md +190 -221
- data/UPGRADING.md +47 -0
- data/lib/jwt/base64.rb +1 -10
- data/lib/jwt/claims/numeric.rb +0 -32
- data/lib/jwt/claims.rb +0 -7
- data/lib/jwt/configuration/container.rb +0 -1
- data/lib/jwt/decode.rb +18 -15
- data/lib/jwt/encoded_token.rb +112 -15
- data/lib/jwt/error.rb +0 -3
- data/lib/jwt/jwa/ecdsa.rb +25 -4
- data/lib/jwt/jwa/hmac.rb +0 -4
- data/lib/jwt/jwa/ps.rb +1 -0
- data/lib/jwt/jwa/rsa.rb +1 -0
- data/lib/jwt/jwa/signing_algorithm.rb +0 -1
- data/lib/jwt/jwa.rb +50 -26
- data/lib/jwt/jwk/ec.rb +52 -62
- data/lib/jwt/jwk/hmac.rb +3 -3
- data/lib/jwt/jwk/key_base.rb +19 -0
- data/lib/jwt/jwk/key_finder.rb +35 -9
- data/lib/jwt/jwk/rsa.rb +5 -1
- data/lib/jwt/jwk.rb +0 -1
- data/lib/jwt/token.rb +26 -7
- data/lib/jwt/version.rb +4 -20
- data/lib/jwt.rb +1 -7
- data/ruby-jwt.gemspec +2 -0
- metadata +33 -14
- data/lib/jwt/claims/verification_methods.rb +0 -20
- data/lib/jwt/claims_validator.rb +0 -18
- data/lib/jwt/deprecations.rb +0 -49
- data/lib/jwt/jwa/compat.rb +0 -32
- data/lib/jwt/jwa/eddsa.rb +0 -35
- data/lib/jwt/jwa/hmac_rbnacl.rb +0 -50
- data/lib/jwt/jwa/hmac_rbnacl_fixed.rb +0 -47
- data/lib/jwt/jwa/wrapper.rb +0 -44
- data/lib/jwt/jwk/okp_rbnacl.rb +0 -109
- data/lib/jwt/verify.rb +0 -40
data/lib/jwt/jwk/ec.rb
CHANGED
@@ -68,11 +68,18 @@ module JWT
|
|
68
68
|
def []=(key, value)
|
69
69
|
raise ArgumentError, 'cannot overwrite cryptographic key attributes' if EC_KEY_ELEMENTS.include?(key.to_sym)
|
70
70
|
|
71
|
-
super
|
71
|
+
super
|
72
72
|
end
|
73
73
|
|
74
74
|
private
|
75
75
|
|
76
|
+
def jwa
|
77
|
+
return super if self[:alg]
|
78
|
+
|
79
|
+
curve_name = self.class.to_openssl_curve(self[:crv])
|
80
|
+
JWA.resolve(JWA::Ecdsa.curve_by_name(curve_name)[:algorithm])
|
81
|
+
end
|
82
|
+
|
76
83
|
def ec_key
|
77
84
|
@ec_key ||= create_ec_key(self[:crv], self[:x], self[:y], self[:d])
|
78
85
|
end
|
@@ -124,10 +131,6 @@ module JWT
|
|
124
131
|
::JWT::Base64.url_encode(octets)
|
125
132
|
end
|
126
133
|
|
127
|
-
def encode_open_ssl_bn(key_part)
|
128
|
-
::JWT::Base64.url_encode(key_part.to_s(BINARY))
|
129
|
-
end
|
130
|
-
|
131
134
|
def parse_ec_key(key)
|
132
135
|
crv, x_octets, y_octets = keypair_components(key)
|
133
136
|
octets = key.private_key&.to_bn&.to_s(BINARY)
|
@@ -140,67 +143,54 @@ module JWT
|
|
140
143
|
}.compact
|
141
144
|
end
|
142
145
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
y_octets = decode_octets(jwk_y)
|
148
|
-
|
149
|
-
point = OpenSSL::PKey::EC::Point.new(
|
150
|
-
OpenSSL::PKey::EC::Group.new(curve),
|
151
|
-
OpenSSL::BN.new([0x04, x_octets, y_octets].pack('Ca*a*'), 2)
|
152
|
-
)
|
153
|
-
|
154
|
-
sequence = if jwk_d
|
155
|
-
# https://datatracker.ietf.org/doc/html/rfc5915.html
|
156
|
-
# ECPrivateKey ::= SEQUENCE {
|
157
|
-
# version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
|
158
|
-
# privateKey OCTET STRING,
|
159
|
-
# parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
|
160
|
-
# publicKey [1] BIT STRING OPTIONAL
|
161
|
-
# }
|
162
|
-
|
163
|
-
OpenSSL::ASN1::Sequence([
|
164
|
-
OpenSSL::ASN1::Integer(1),
|
165
|
-
OpenSSL::ASN1::OctetString(OpenSSL::BN.new(decode_octets(jwk_d), 2).to_s(2)),
|
166
|
-
OpenSSL::ASN1::ObjectId(curve, 0, :EXPLICIT),
|
167
|
-
OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed), 1, :EXPLICIT)
|
168
|
-
])
|
169
|
-
else
|
170
|
-
OpenSSL::ASN1::Sequence([
|
171
|
-
OpenSSL::ASN1::Sequence([OpenSSL::ASN1::ObjectId('id-ecPublicKey'), OpenSSL::ASN1::ObjectId(curve)]),
|
172
|
-
OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed))
|
173
|
-
])
|
174
|
-
end
|
146
|
+
def create_point(jwk_crv, jwk_x, jwk_y)
|
147
|
+
curve = EC.to_openssl_curve(jwk_crv)
|
148
|
+
x_octets = decode_octets(jwk_x)
|
149
|
+
y_octets = decode_octets(jwk_y)
|
175
150
|
|
151
|
+
# The details of the `Point` instantiation are covered in:
|
152
|
+
# - https://docs.ruby-lang.org/en/2.4.0/OpenSSL/PKey/EC.html
|
153
|
+
# - https://www.openssl.org/docs/manmaster/man3/EC_POINT_new.html
|
154
|
+
# - https://tools.ietf.org/html/rfc5480#section-2.2
|
155
|
+
# - https://www.secg.org/SEC1-Ver-1.0.pdf
|
156
|
+
# Section 2.3.3 of the last of these references specifies that the
|
157
|
+
# encoding of an uncompressed point consists of the byte `0x04` followed
|
158
|
+
# by the x value then the y value.
|
159
|
+
OpenSSL::PKey::EC::Point.new(
|
160
|
+
OpenSSL::PKey::EC::Group.new(curve),
|
161
|
+
OpenSSL::BN.new([0x04, x_octets, y_octets].pack('Ca*a*'), 2)
|
162
|
+
)
|
163
|
+
end
|
164
|
+
|
165
|
+
if ::JWT.openssl_3?
|
166
|
+
def create_ec_key(jwk_crv, jwk_x, jwk_y, jwk_d)
|
167
|
+
point = create_point(jwk_crv, jwk_x, jwk_y)
|
168
|
+
|
169
|
+
return ::JWT::JWA::Ecdsa.create_public_key_from_point(point) unless jwk_d
|
170
|
+
|
171
|
+
# https://datatracker.ietf.org/doc/html/rfc5915.html
|
172
|
+
# ECPrivateKey ::= SEQUENCE {
|
173
|
+
# version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
|
174
|
+
# privateKey OCTET STRING,
|
175
|
+
# parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
|
176
|
+
# publicKey [1] BIT STRING OPTIONAL
|
177
|
+
# }
|
178
|
+
|
179
|
+
sequence = OpenSSL::ASN1::Sequence([
|
180
|
+
OpenSSL::ASN1::Integer(1),
|
181
|
+
OpenSSL::ASN1::OctetString(OpenSSL::BN.new(decode_octets(jwk_d), 2).to_s(2)),
|
182
|
+
OpenSSL::ASN1::ObjectId(point.group.curve_name, 0, :EXPLICIT),
|
183
|
+
OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed), 1, :EXPLICIT)
|
184
|
+
])
|
176
185
|
OpenSSL::PKey::EC.new(sequence.to_der)
|
177
186
|
end
|
178
187
|
else
|
179
188
|
def create_ec_key(jwk_crv, jwk_x, jwk_y, jwk_d)
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
key = OpenSSL::PKey::EC.new(curve)
|
186
|
-
|
187
|
-
# The details of the `Point` instantiation are covered in:
|
188
|
-
# - https://docs.ruby-lang.org/en/2.4.0/OpenSSL/PKey/EC.html
|
189
|
-
# - https://www.openssl.org/docs/manmaster/man3/EC_POINT_new.html
|
190
|
-
# - https://tools.ietf.org/html/rfc5480#section-2.2
|
191
|
-
# - https://www.secg.org/SEC1-Ver-1.0.pdf
|
192
|
-
# Section 2.3.3 of the last of these references specifies that the
|
193
|
-
# encoding of an uncompressed point consists of the byte `0x04` followed
|
194
|
-
# by the x value then the y value.
|
195
|
-
point = OpenSSL::PKey::EC::Point.new(
|
196
|
-
OpenSSL::PKey::EC::Group.new(curve),
|
197
|
-
OpenSSL::BN.new([0x04, x_octets, y_octets].pack('Ca*a*'), 2)
|
198
|
-
)
|
199
|
-
|
200
|
-
key.public_key = point
|
201
|
-
key.private_key = OpenSSL::BN.new(decode_octets(jwk_d), 2) if jwk_d
|
202
|
-
|
203
|
-
key
|
189
|
+
point = create_point(jwk_crv, jwk_x, jwk_y)
|
190
|
+
|
191
|
+
::JWT::JWA::Ecdsa.create_public_key_from_point(point).tap do |key|
|
192
|
+
key.private_key = OpenSSL::BN.new(decode_octets(jwk_d), 2) if jwk_d
|
193
|
+
end
|
204
194
|
end
|
205
195
|
end
|
206
196
|
|
@@ -209,7 +199,7 @@ module JWT
|
|
209
199
|
# Some base64 encoders on some platform omit a single 0-byte at
|
210
200
|
# the start of either Y or X coordinate of the elliptic curve point.
|
211
201
|
# This leads to an encoding error when data is passed to OpenSSL BN.
|
212
|
-
# It is know to have
|
202
|
+
# It is know to have happened to exported JWKs on a Java application and
|
213
203
|
# on a Flutter/Dart application (both iOS and Android). All that is
|
214
204
|
# needed to fix the problem is adding a leading 0-byte. We know the
|
215
205
|
# required byte is 0 because with any other byte the point is no longer
|
data/lib/jwt/jwk/hmac.rb
CHANGED
@@ -64,13 +64,13 @@ module JWT
|
|
64
64
|
def []=(key, value)
|
65
65
|
raise ArgumentError, 'cannot overwrite cryptographic key attributes' if HMAC_KEY_ELEMENTS.include?(key.to_sym)
|
66
66
|
|
67
|
-
super
|
67
|
+
super
|
68
68
|
end
|
69
69
|
|
70
70
|
private
|
71
71
|
|
72
72
|
def secret
|
73
|
-
self[:k]
|
73
|
+
@secret ||= ::JWT::Base64.url_decode(self[:k])
|
74
74
|
end
|
75
75
|
|
76
76
|
def extract_key_params(key)
|
@@ -78,7 +78,7 @@ module JWT
|
|
78
78
|
when JWT::JWK::HMAC
|
79
79
|
key.export(include_private: true)
|
80
80
|
when String # Accept String key as input
|
81
|
-
{ kty: KTY, k: key }
|
81
|
+
{ kty: KTY, k: ::JWT::Base64.url_encode(key) }
|
82
82
|
when Hash
|
83
83
|
key.transform_keys(&:to_sym)
|
84
84
|
else
|
data/lib/jwt/jwk/key_base.rb
CHANGED
@@ -42,6 +42,19 @@ module JWT
|
|
42
42
|
other.is_a?(::JWT::JWK::KeyBase) && self[:kid] == other[:kid]
|
43
43
|
end
|
44
44
|
|
45
|
+
def verify(**kwargs)
|
46
|
+
jwa.verify(**kwargs, verification_key: verify_key)
|
47
|
+
end
|
48
|
+
|
49
|
+
def sign(**kwargs)
|
50
|
+
jwa.sign(**kwargs, signing_key: signing_key)
|
51
|
+
end
|
52
|
+
|
53
|
+
# @api private
|
54
|
+
def jwa_header
|
55
|
+
jwa.header
|
56
|
+
end
|
57
|
+
|
45
58
|
alias eql? ==
|
46
59
|
|
47
60
|
def <=>(other)
|
@@ -52,6 +65,12 @@ module JWT
|
|
52
65
|
|
53
66
|
private
|
54
67
|
|
68
|
+
def jwa
|
69
|
+
raise JWT::JWKError, 'Could not resolve the JWA, the "alg" parameter is missing' unless self[:alg]
|
70
|
+
|
71
|
+
JWA.resolve(self[:alg])
|
72
|
+
end
|
73
|
+
|
55
74
|
attr_reader :parameters
|
56
75
|
end
|
57
76
|
end
|
data/lib/jwt/jwk/key_finder.rb
CHANGED
@@ -2,8 +2,16 @@
|
|
2
2
|
|
3
3
|
module JWT
|
4
4
|
module JWK
|
5
|
-
#
|
5
|
+
# JSON Web Key keyfinder
|
6
|
+
# To find the key for a given kid
|
6
7
|
class KeyFinder
|
8
|
+
# Initializes a new KeyFinder instance.
|
9
|
+
# @param [Hash] options the options to create a KeyFinder with
|
10
|
+
# @option options [Proc, JWT::JWK::Set] :jwks the jwks or a loader proc
|
11
|
+
# @option options [Boolean] :allow_nil_kid whether to allow nil kid
|
12
|
+
# @option options [Array] :key_fields the fields to use for key matching,
|
13
|
+
# the order of the fields are used to determine
|
14
|
+
# the priority of the keys.
|
7
15
|
def initialize(options)
|
8
16
|
@allow_nil_kid = options[:allow_nil_kid]
|
9
17
|
jwks_or_loader = options[:jwks]
|
@@ -13,13 +21,16 @@ module JWT
|
|
13
21
|
else
|
14
22
|
->(_options) { jwks_or_loader }
|
15
23
|
end
|
24
|
+
|
25
|
+
@key_fields = options[:key_fields] || %i[kid]
|
16
26
|
end
|
17
27
|
|
18
|
-
|
19
|
-
|
20
|
-
|
28
|
+
# Returns the verification key for the given kid
|
29
|
+
# @param [String] kid the key id
|
30
|
+
def key_for(kid, key_field = :kid)
|
31
|
+
raise ::JWT::DecodeError, "Invalid type for #{key_field} header parameter" unless kid.nil? || kid.is_a?(String)
|
21
32
|
|
22
|
-
jwk = resolve_key(kid)
|
33
|
+
jwk = resolve_key(kid, key_field)
|
23
34
|
|
24
35
|
raise ::JWT::DecodeError, 'No keys found in jwks' unless @jwks.any?
|
25
36
|
raise ::JWT::DecodeError, "Could not find public key for kid #{kid}" unless jwk
|
@@ -27,19 +38,34 @@ module JWT
|
|
27
38
|
jwk.verify_key
|
28
39
|
end
|
29
40
|
|
41
|
+
# Returns the key for the given token
|
42
|
+
# @param [JWT::EncodedToken] token the token
|
43
|
+
def call(token)
|
44
|
+
@key_fields.each do |key_field|
|
45
|
+
field_value = token.header[key_field.to_s]
|
46
|
+
|
47
|
+
return key_for(field_value, key_field) if field_value
|
48
|
+
end
|
49
|
+
|
50
|
+
raise ::JWT::DecodeError, 'No key id (kid) or x5t found from token headers' unless @allow_nil_kid
|
51
|
+
|
52
|
+
kid = token.header['kid']
|
53
|
+
key_for(kid)
|
54
|
+
end
|
55
|
+
|
30
56
|
private
|
31
57
|
|
32
|
-
def resolve_key(kid)
|
33
|
-
key_matcher = ->(key) { (kid.nil? && @allow_nil_kid) || key[
|
58
|
+
def resolve_key(kid, key_field)
|
59
|
+
key_matcher = ->(key) { (kid.nil? && @allow_nil_kid) || key[key_field] == kid }
|
34
60
|
|
35
61
|
# First try without invalidation to facilitate application caching
|
36
|
-
@jwks ||= JWT::JWK::Set.new(@jwks_loader.call(
|
62
|
+
@jwks ||= JWT::JWK::Set.new(@jwks_loader.call(key_field => kid))
|
37
63
|
jwk = @jwks.find { |key| key_matcher.call(key) }
|
38
64
|
|
39
65
|
return jwk if jwk
|
40
66
|
|
41
67
|
# Second try, invalidate for backwards compatibility
|
42
|
-
@jwks = JWT::JWK::Set.new(@jwks_loader.call(invalidate: true, kid_not_found: true,
|
68
|
+
@jwks = JWT::JWK::Set.new(@jwks_loader.call(invalidate: true, kid_not_found: true, key_field => kid))
|
43
69
|
@jwks.find { |key| key_matcher.call(key) }
|
44
70
|
end
|
45
71
|
end
|
data/lib/jwt/jwk/rsa.rb
CHANGED
@@ -51,6 +51,7 @@ module JWT
|
|
51
51
|
def export(options = {})
|
52
52
|
exported = parameters.clone
|
53
53
|
exported.reject! { |k, _| RSA_PRIVATE_KEY_ELEMENTS.include? k } unless private? && options[:include_private] == true
|
54
|
+
|
54
55
|
exported
|
55
56
|
end
|
56
57
|
|
@@ -67,7 +68,7 @@ module JWT
|
|
67
68
|
def []=(key, value)
|
68
69
|
raise ArgumentError, 'cannot overwrite cryptographic key attributes' if RSA_KEY_ELEMENTS.include?(key.to_sym)
|
69
70
|
|
70
|
-
super
|
71
|
+
super
|
71
72
|
end
|
72
73
|
|
73
74
|
private
|
@@ -165,6 +166,8 @@ module JWT
|
|
165
166
|
end
|
166
167
|
end
|
167
168
|
|
169
|
+
# :nocov:
|
170
|
+
# Before openssl 2.0, we need to use the accessors to set the key
|
168
171
|
def create_rsa_key_using_accessors(rsa_parameters) # rubocop:disable Metrics/AbcSize
|
169
172
|
validate_rsa_parameters!(rsa_parameters)
|
170
173
|
|
@@ -179,6 +182,7 @@ module JWT
|
|
179
182
|
rsa_key.iqmp = rsa_parameters[:qi] if rsa_parameters[:qi]
|
180
183
|
end
|
181
184
|
end
|
185
|
+
# :nocov:
|
182
186
|
|
183
187
|
def validate_rsa_parameters!(rsa_parameters)
|
184
188
|
return unless rsa_parameters.key?(:d)
|
data/lib/jwt/jwk.rb
CHANGED
data/lib/jwt/token.rb
CHANGED
@@ -15,8 +15,6 @@ module JWT
|
|
15
15
|
# token.header # => {"custom"=>"value", "alg"=>"HS256"}
|
16
16
|
#
|
17
17
|
class Token
|
18
|
-
include Claims::VerificationMethods
|
19
|
-
|
20
18
|
# Initializes a new Token instance.
|
21
19
|
#
|
22
20
|
# @param header [Hash] the header of the JWT token.
|
@@ -89,21 +87,42 @@ module JWT
|
|
89
87
|
|
90
88
|
# Signs the JWT token.
|
91
89
|
#
|
90
|
+
# @param key [String, JWT::JWK::KeyBase] the key to use for signing.
|
92
91
|
# @param algorithm [String, Object] the algorithm to use for signing.
|
93
|
-
# @param key [String] the key to use for signing.
|
94
92
|
# @return [void]
|
95
93
|
# @raise [JWT::EncodeError] if the token is already signed or other problems when signing
|
96
|
-
def sign!(
|
94
|
+
def sign!(key:, algorithm: nil)
|
97
95
|
raise ::JWT::EncodeError, 'Token already signed' if @signature
|
98
96
|
|
99
|
-
JWA.
|
100
|
-
header.merge!(
|
101
|
-
@signature =
|
97
|
+
JWA.create_signer(algorithm: algorithm, key: key).tap do |signer|
|
98
|
+
header.merge!(signer.jwa_header) { |_key, old, _new| old }
|
99
|
+
@signature = signer.sign(data: signing_input)
|
102
100
|
end
|
103
101
|
|
104
102
|
nil
|
105
103
|
end
|
106
104
|
|
105
|
+
# Verifies the claims of the token.
|
106
|
+
# @param options [Array<Symbol>, Hash] the claims to verify.
|
107
|
+
# @raise [JWT::DecodeError] if the claims are invalid.
|
108
|
+
def verify_claims!(*options)
|
109
|
+
Claims::Verifier.verify!(self, *options)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Returns the errors of the claims of the token.
|
113
|
+
# @param options [Array<Symbol>, Hash] the claims to verify.
|
114
|
+
# @return [Array<Symbol>] the errors of the claims.
|
115
|
+
def claim_errors(*options)
|
116
|
+
Claims::Verifier.errors(self, *options)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns whether the claims of the token are valid.
|
120
|
+
# @param options [Array<Symbol>, Hash] the claims to verify.
|
121
|
+
# @return [Boolean] whether the claims are valid.
|
122
|
+
def valid_claims?(*options)
|
123
|
+
claim_errors(*options).empty?
|
124
|
+
end
|
125
|
+
|
107
126
|
# Returns the JWT token as a string.
|
108
127
|
#
|
109
128
|
# @return [String] the JWT token as a string.
|
data/lib/jwt/version.rb
CHANGED
@@ -12,11 +12,11 @@ module JWT
|
|
12
12
|
Gem::Version.new(VERSION::STRING)
|
13
13
|
end
|
14
14
|
|
15
|
-
#
|
15
|
+
# Version constants
|
16
16
|
module VERSION
|
17
|
-
MAJOR =
|
18
|
-
MINOR =
|
19
|
-
TINY =
|
17
|
+
MAJOR = 3
|
18
|
+
MINOR = 1
|
19
|
+
TINY = 0
|
20
20
|
PRE = nil
|
21
21
|
|
22
22
|
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
@@ -32,22 +32,6 @@ module JWT
|
|
32
32
|
true if 3 * 0x10000000 <= OpenSSL::OPENSSL_VERSION_NUMBER
|
33
33
|
end
|
34
34
|
|
35
|
-
# Checks if the RbNaCl library is defined.
|
36
|
-
#
|
37
|
-
# @return [Boolean] true if RbNaCl is defined, false otherwise.
|
38
|
-
# @api private
|
39
|
-
def self.rbnacl?
|
40
|
-
defined?(::RbNaCl)
|
41
|
-
end
|
42
|
-
|
43
|
-
# Checks if the RbNaCl library version is 6.0.0 or greater.
|
44
|
-
#
|
45
|
-
# @return [Boolean] true if RbNaCl version is 6.0.0 or greater, false otherwise.
|
46
|
-
# @api private
|
47
|
-
def self.rbnacl_6_or_greater?
|
48
|
-
rbnacl? && ::Gem::Version.new(::RbNaCl::VERSION) >= ::Gem::Version.new('6.0.0')
|
49
|
-
end
|
50
|
-
|
51
35
|
# Checks if there is an OpenSSL 3 HMAC empty key regression.
|
52
36
|
#
|
53
37
|
# @return [Boolean] true if there is an OpenSSL 3 HMAC empty key regression, false otherwise.
|
data/lib/jwt.rb
CHANGED
@@ -5,7 +5,6 @@ require 'jwt/base64'
|
|
5
5
|
require 'jwt/json'
|
6
6
|
require 'jwt/decode'
|
7
7
|
require 'jwt/configuration'
|
8
|
-
require 'jwt/deprecations'
|
9
8
|
require 'jwt/encode'
|
10
9
|
require 'jwt/error'
|
11
10
|
require 'jwt/jwk'
|
@@ -13,9 +12,6 @@ require 'jwt/claims'
|
|
13
12
|
require 'jwt/encoded_token'
|
14
13
|
require 'jwt/token'
|
15
14
|
|
16
|
-
require 'jwt/claims_validator'
|
17
|
-
require 'jwt/verify'
|
18
|
-
|
19
15
|
# JSON Web Token implementation
|
20
16
|
#
|
21
17
|
# Should be up to date with the latest spec:
|
@@ -47,8 +43,6 @@ module JWT
|
|
47
43
|
# @param options [Hash] additional options for decoding.
|
48
44
|
# @return [Array<Hash>] the decoded payload and headers.
|
49
45
|
def decode(jwt, key = nil, verify = true, options = {}, &keyfinder) # rubocop:disable Style/OptionalBooleanParameter
|
50
|
-
|
51
|
-
Decode.new(jwt, key, verify, configuration.decode.to_h.merge(options), &keyfinder).decode_segments
|
52
|
-
end
|
46
|
+
Decode.new(jwt, key, verify, configuration.decode.to_h.merge(options), &keyfinder).decode_segments
|
53
47
|
end
|
54
48
|
end
|
data/ruby-jwt.gemspec
CHANGED
@@ -35,6 +35,8 @@ Gem::Specification.new do |spec|
|
|
35
35
|
|
36
36
|
spec.add_development_dependency 'appraisal'
|
37
37
|
spec.add_development_dependency 'bundler'
|
38
|
+
spec.add_development_dependency 'irb'
|
39
|
+
spec.add_development_dependency 'logger'
|
38
40
|
spec.add_development_dependency 'rake'
|
39
41
|
spec.add_development_dependency 'rspec'
|
40
42
|
spec.add_development_dependency 'rubocop'
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jwt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Rudat
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: base64
|
@@ -51,6 +51,34 @@ dependencies:
|
|
51
51
|
- - ">="
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: '0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: irb
|
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'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: logger
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
54
82
|
- !ruby/object:Gem::Dependency
|
55
83
|
name: rake
|
56
84
|
requirement: !ruby/object:Gem::Requirement
|
@@ -120,6 +148,7 @@ files:
|
|
120
148
|
- CONTRIBUTING.md
|
121
149
|
- LICENSE
|
122
150
|
- README.md
|
151
|
+
- UPGRADING.md
|
123
152
|
- lib/jwt.rb
|
124
153
|
- lib/jwt/base64.rb
|
125
154
|
- lib/jwt/claims.rb
|
@@ -134,44 +163,34 @@ files:
|
|
134
163
|
- lib/jwt/claims/numeric.rb
|
135
164
|
- lib/jwt/claims/required.rb
|
136
165
|
- lib/jwt/claims/subject.rb
|
137
|
-
- lib/jwt/claims/verification_methods.rb
|
138
166
|
- lib/jwt/claims/verifier.rb
|
139
|
-
- lib/jwt/claims_validator.rb
|
140
167
|
- lib/jwt/configuration.rb
|
141
168
|
- lib/jwt/configuration/container.rb
|
142
169
|
- lib/jwt/configuration/decode_configuration.rb
|
143
170
|
- lib/jwt/configuration/jwk_configuration.rb
|
144
171
|
- lib/jwt/decode.rb
|
145
|
-
- lib/jwt/deprecations.rb
|
146
172
|
- lib/jwt/encode.rb
|
147
173
|
- lib/jwt/encoded_token.rb
|
148
174
|
- lib/jwt/error.rb
|
149
175
|
- lib/jwt/json.rb
|
150
176
|
- lib/jwt/jwa.rb
|
151
|
-
- lib/jwt/jwa/compat.rb
|
152
177
|
- lib/jwt/jwa/ecdsa.rb
|
153
|
-
- lib/jwt/jwa/eddsa.rb
|
154
178
|
- lib/jwt/jwa/hmac.rb
|
155
|
-
- lib/jwt/jwa/hmac_rbnacl.rb
|
156
|
-
- lib/jwt/jwa/hmac_rbnacl_fixed.rb
|
157
179
|
- lib/jwt/jwa/none.rb
|
158
180
|
- lib/jwt/jwa/ps.rb
|
159
181
|
- lib/jwt/jwa/rsa.rb
|
160
182
|
- lib/jwt/jwa/signing_algorithm.rb
|
161
183
|
- lib/jwt/jwa/unsupported.rb
|
162
|
-
- lib/jwt/jwa/wrapper.rb
|
163
184
|
- lib/jwt/jwk.rb
|
164
185
|
- lib/jwt/jwk/ec.rb
|
165
186
|
- lib/jwt/jwk/hmac.rb
|
166
187
|
- lib/jwt/jwk/key_base.rb
|
167
188
|
- lib/jwt/jwk/key_finder.rb
|
168
189
|
- lib/jwt/jwk/kid_as_key_digest.rb
|
169
|
-
- lib/jwt/jwk/okp_rbnacl.rb
|
170
190
|
- lib/jwt/jwk/rsa.rb
|
171
191
|
- lib/jwt/jwk/set.rb
|
172
192
|
- lib/jwt/jwk/thumbprint.rb
|
173
193
|
- lib/jwt/token.rb
|
174
|
-
- lib/jwt/verify.rb
|
175
194
|
- lib/jwt/version.rb
|
176
195
|
- lib/jwt/x5c_key_finder.rb
|
177
196
|
- ruby-jwt.gemspec
|
@@ -180,7 +199,7 @@ licenses:
|
|
180
199
|
- MIT
|
181
200
|
metadata:
|
182
201
|
bug_tracker_uri: https://github.com/jwt/ruby-jwt/issues
|
183
|
-
changelog_uri: https://github.com/jwt/ruby-jwt/blob/
|
202
|
+
changelog_uri: https://github.com/jwt/ruby-jwt/blob/v3.1.0/CHANGELOG.md
|
184
203
|
rubygems_mfa_required: 'true'
|
185
204
|
rdoc_options: []
|
186
205
|
require_paths:
|
@@ -196,7 +215,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
196
215
|
- !ruby/object:Gem::Version
|
197
216
|
version: '0'
|
198
217
|
requirements: []
|
199
|
-
rubygems_version: 3.6.
|
218
|
+
rubygems_version: 3.6.7
|
200
219
|
specification_version: 4
|
201
220
|
summary: JSON Web Token implementation in Ruby
|
202
221
|
test_files: []
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module JWT
|
4
|
-
module Claims
|
5
|
-
# @api private
|
6
|
-
module VerificationMethods
|
7
|
-
def verify_claims!(*options)
|
8
|
-
Verifier.verify!(self, *options)
|
9
|
-
end
|
10
|
-
|
11
|
-
def claim_errors(*options)
|
12
|
-
Verifier.errors(self, *options)
|
13
|
-
end
|
14
|
-
|
15
|
-
def valid_claims?(*options)
|
16
|
-
claim_errors(*options).empty?
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
data/lib/jwt/claims_validator.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module JWT
|
4
|
-
# @deprecated Use `Claims.verify_payload!` directly instead.
|
5
|
-
class ClaimsValidator
|
6
|
-
# @deprecated Use `Claims.verify_payload!` directly instead.
|
7
|
-
def initialize(payload)
|
8
|
-
Deprecations.warning('The ::JWT::ClaimsValidator class is deprecated and will be removed in the next major version of ruby-jwt')
|
9
|
-
@payload = payload
|
10
|
-
end
|
11
|
-
|
12
|
-
# @deprecated Use `Claims.verify_payload!` directly instead.
|
13
|
-
def validate!
|
14
|
-
Claims.verify_payload!(@payload, :numeric)
|
15
|
-
true
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/lib/jwt/deprecations.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module JWT
|
4
|
-
# Deprecations module to handle deprecation warnings in the gem
|
5
|
-
# @api private
|
6
|
-
module Deprecations
|
7
|
-
class << self
|
8
|
-
def context
|
9
|
-
yield.tap { emit_warnings }
|
10
|
-
ensure
|
11
|
-
Thread.current[:jwt_warning_store] = nil
|
12
|
-
end
|
13
|
-
|
14
|
-
def warning(message, only_if_valid: false)
|
15
|
-
method_name = only_if_valid ? :store : :warn
|
16
|
-
case JWT.configuration.deprecation_warnings
|
17
|
-
when :once
|
18
|
-
return if record_warned(message)
|
19
|
-
when :warn
|
20
|
-
# noop
|
21
|
-
else
|
22
|
-
return
|
23
|
-
end
|
24
|
-
|
25
|
-
send(method_name, "[DEPRECATION WARNING] #{message}")
|
26
|
-
end
|
27
|
-
|
28
|
-
def store(message)
|
29
|
-
(Thread.current[:jwt_warning_store] ||= []) << message
|
30
|
-
end
|
31
|
-
|
32
|
-
def emit_warnings
|
33
|
-
return if Thread.current[:jwt_warning_store].nil?
|
34
|
-
|
35
|
-
Thread.current[:jwt_warning_store].each { |warning| warn(warning) }
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def record_warned(message)
|
41
|
-
@warned ||= []
|
42
|
-
return true if @warned.include?(message)
|
43
|
-
|
44
|
-
@warned << message
|
45
|
-
false
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|