jwt 2.8.2 → 3.1.1
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 +149 -31
- data/CODE_OF_CONDUCT.md +14 -14
- data/CONTRIBUTING.md +9 -10
- data/README.md +299 -234
- data/UPGRADING.md +47 -0
- data/lib/jwt/base64.rb +4 -10
- data/lib/jwt/claims/audience.rb +30 -0
- data/lib/jwt/claims/crit.rb +35 -0
- data/lib/jwt/claims/decode_verifier.rb +40 -0
- data/lib/jwt/claims/expiration.rb +32 -0
- data/lib/jwt/claims/issued_at.rb +22 -0
- data/lib/jwt/claims/issuer.rb +34 -0
- data/lib/jwt/claims/jwt_id.rb +35 -0
- data/lib/jwt/claims/not_before.rb +32 -0
- data/lib/jwt/claims/numeric.rb +45 -0
- data/lib/jwt/claims/required.rb +33 -0
- data/lib/jwt/claims/subject.rb +30 -0
- data/lib/jwt/claims/verifier.rb +61 -0
- data/lib/jwt/claims.rb +67 -0
- data/lib/jwt/configuration/container.rb +20 -1
- data/lib/jwt/configuration/decode_configuration.rb +24 -0
- data/lib/jwt/configuration/jwk_configuration.rb +1 -0
- data/lib/jwt/configuration.rb +8 -0
- data/lib/jwt/decode.rb +42 -81
- data/lib/jwt/encode.rb +17 -60
- data/lib/jwt/encoded_token.rb +236 -0
- data/lib/jwt/error.rb +32 -1
- data/lib/jwt/json.rb +1 -1
- data/lib/jwt/jwa/ecdsa.rb +59 -24
- data/lib/jwt/jwa/hmac.rb +22 -19
- data/lib/jwt/jwa/none.rb +8 -3
- data/lib/jwt/jwa/ps.rb +21 -15
- data/lib/jwt/jwa/rsa.rb +21 -10
- data/lib/jwt/jwa/signing_algorithm.rb +62 -0
- data/lib/jwt/jwa/unsupported.rb +9 -8
- data/lib/jwt/jwa.rb +76 -35
- data/lib/jwt/jwk/ec.rb +54 -65
- data/lib/jwt/jwk/hmac.rb +5 -6
- data/lib/jwt/jwk/key_base.rb +16 -1
- data/lib/jwt/jwk/key_finder.rb +35 -8
- data/lib/jwt/jwk/kid_as_key_digest.rb +1 -0
- data/lib/jwt/jwk/rsa.rb +7 -4
- data/lib/jwt/jwk/set.rb +2 -0
- data/lib/jwt/jwk.rb +1 -1
- data/lib/jwt/token.rb +131 -0
- data/lib/jwt/version.rb +24 -19
- data/lib/jwt.rb +18 -4
- data/ruby-jwt.gemspec +2 -0
- metadata +49 -15
- data/lib/jwt/claims_validator.rb +0 -37
- data/lib/jwt/deprecations.rb +0 -48
- data/lib/jwt/jwa/eddsa.rb +0 -42
- data/lib/jwt/jwa/hmac_rbnacl.rb +0 -50
- data/lib/jwt/jwa/hmac_rbnacl_fixed.rb +0 -46
- data/lib/jwt/jwa/wrapper.rb +0 -26
- data/lib/jwt/jwk/okp_rbnacl.rb +0 -110
- data/lib/jwt/verify.rb +0 -117
data/lib/jwt/jwk/hmac.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
module JWT
|
4
4
|
module JWK
|
5
|
+
# JWK for HMAC keys
|
5
6
|
class HMAC < KeyBase
|
6
7
|
KTY = 'oct'
|
7
8
|
KTYS = [KTY, String, JWT::JWK::HMAC].freeze
|
@@ -61,17 +62,15 @@ module JWT
|
|
61
62
|
end
|
62
63
|
|
63
64
|
def []=(key, value)
|
64
|
-
if HMAC_KEY_ELEMENTS.include?(key.to_sym)
|
65
|
-
raise ArgumentError, 'cannot overwrite cryptographic key attributes'
|
66
|
-
end
|
65
|
+
raise ArgumentError, 'cannot overwrite cryptographic key attributes' if HMAC_KEY_ELEMENTS.include?(key.to_sym)
|
67
66
|
|
68
|
-
super
|
67
|
+
super
|
69
68
|
end
|
70
69
|
|
71
70
|
private
|
72
71
|
|
73
72
|
def secret
|
74
|
-
self[:k]
|
73
|
+
@secret ||= ::JWT::Base64.url_decode(self[:k])
|
75
74
|
end
|
76
75
|
|
77
76
|
def extract_key_params(key)
|
@@ -79,7 +78,7 @@ module JWT
|
|
79
78
|
when JWT::JWK::HMAC
|
80
79
|
key.export(include_private: true)
|
81
80
|
when String # Accept String key as input
|
82
|
-
{ kty: KTY, k: key }
|
81
|
+
{ kty: KTY, k: ::JWT::Base64.url_encode(key) }
|
83
82
|
when Hash
|
84
83
|
key.transform_keys(&:to_sym)
|
85
84
|
else
|
data/lib/jwt/jwk/key_base.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
module JWT
|
4
4
|
module JWK
|
5
|
+
# Base for JWK implementations
|
5
6
|
class KeyBase
|
6
7
|
def self.inherited(klass)
|
7
8
|
super
|
@@ -41,6 +42,14 @@ module JWT
|
|
41
42
|
other.is_a?(::JWT::JWK::KeyBase) && self[:kid] == other[:kid]
|
42
43
|
end
|
43
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
|
+
|
44
53
|
alias eql? ==
|
45
54
|
|
46
55
|
def <=>(other)
|
@@ -49,7 +58,13 @@ module JWT
|
|
49
58
|
self[:kid] <=> other[:kid]
|
50
59
|
end
|
51
60
|
|
52
|
-
|
61
|
+
def jwa
|
62
|
+
raise JWT::JWKError, 'Could not resolve the JWA, the "alg" parameter is missing' unless self[:alg]
|
63
|
+
|
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
|
67
|
+
end
|
53
68
|
|
54
69
|
attr_reader :parameters
|
55
70
|
end
|
data/lib/jwt/jwk/key_finder.rb
CHANGED
@@ -2,7 +2,16 @@
|
|
2
2
|
|
3
3
|
module JWT
|
4
4
|
module JWK
|
5
|
+
# JSON Web Key keyfinder
|
6
|
+
# To find the key for a given kid
|
5
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.
|
6
15
|
def initialize(options)
|
7
16
|
@allow_nil_kid = options[:allow_nil_kid]
|
8
17
|
jwks_or_loader = options[:jwks]
|
@@ -12,13 +21,16 @@ module JWT
|
|
12
21
|
else
|
13
22
|
->(_options) { jwks_or_loader }
|
14
23
|
end
|
24
|
+
|
25
|
+
@key_fields = options[:key_fields] || %i[kid]
|
15
26
|
end
|
16
27
|
|
17
|
-
|
18
|
-
|
19
|
-
|
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)
|
20
32
|
|
21
|
-
jwk = resolve_key(kid)
|
33
|
+
jwk = resolve_key(kid, key_field)
|
22
34
|
|
23
35
|
raise ::JWT::DecodeError, 'No keys found in jwks' unless @jwks.any?
|
24
36
|
raise ::JWT::DecodeError, "Could not find public key for kid #{kid}" unless jwk
|
@@ -26,19 +38,34 @@ module JWT
|
|
26
38
|
jwk.verify_key
|
27
39
|
end
|
28
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
|
+
|
29
56
|
private
|
30
57
|
|
31
|
-
def resolve_key(kid)
|
32
|
-
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 }
|
33
60
|
|
34
61
|
# First try without invalidation to facilitate application caching
|
35
|
-
@jwks ||= JWT::JWK::Set.new(@jwks_loader.call(
|
62
|
+
@jwks ||= JWT::JWK::Set.new(@jwks_loader.call(key_field => kid))
|
36
63
|
jwk = @jwks.find { |key| key_matcher.call(key) }
|
37
64
|
|
38
65
|
return jwk if jwk
|
39
66
|
|
40
67
|
# Second try, invalidate for backwards compatibility
|
41
|
-
@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))
|
42
69
|
@jwks.find { |key| key_matcher.call(key) }
|
43
70
|
end
|
44
71
|
end
|
data/lib/jwt/jwk/rsa.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
module JWT
|
4
4
|
module JWK
|
5
|
+
# JSON Web Key (JWK) representation of a RSA key
|
5
6
|
class RSA < KeyBase # rubocop:disable Metrics/ClassLength
|
6
7
|
BINARY = 2
|
7
8
|
KTY = 'RSA'
|
@@ -50,6 +51,7 @@ module JWT
|
|
50
51
|
def export(options = {})
|
51
52
|
exported = parameters.clone
|
52
53
|
exported.reject! { |k, _| RSA_PRIVATE_KEY_ELEMENTS.include? k } unless private? && options[:include_private] == true
|
54
|
+
|
53
55
|
exported
|
54
56
|
end
|
55
57
|
|
@@ -64,11 +66,9 @@ module JWT
|
|
64
66
|
end
|
65
67
|
|
66
68
|
def []=(key, value)
|
67
|
-
if RSA_KEY_ELEMENTS.include?(key.to_sym)
|
68
|
-
raise ArgumentError, 'cannot overwrite cryptographic key attributes'
|
69
|
-
end
|
69
|
+
raise ArgumentError, 'cannot overwrite cryptographic key attributes' if RSA_KEY_ELEMENTS.include?(key.to_sym)
|
70
70
|
|
71
|
-
super
|
71
|
+
super
|
72
72
|
end
|
73
73
|
|
74
74
|
private
|
@@ -166,6 +166,8 @@ module JWT
|
|
166
166
|
end
|
167
167
|
end
|
168
168
|
|
169
|
+
# :nocov:
|
170
|
+
# Before openssl 2.0, we need to use the accessors to set the key
|
169
171
|
def create_rsa_key_using_accessors(rsa_parameters) # rubocop:disable Metrics/AbcSize
|
170
172
|
validate_rsa_parameters!(rsa_parameters)
|
171
173
|
|
@@ -180,6 +182,7 @@ module JWT
|
|
180
182
|
rsa_key.iqmp = rsa_parameters[:qi] if rsa_parameters[:qi]
|
181
183
|
end
|
182
184
|
end
|
185
|
+
# :nocov:
|
183
186
|
|
184
187
|
def validate_rsa_parameters!(rsa_parameters)
|
185
188
|
return unless rsa_parameters.key?(:d)
|
data/lib/jwt/jwk/set.rb
CHANGED
data/lib/jwt/jwk.rb
CHANGED
@@ -4,6 +4,7 @@ require_relative 'jwk/key_finder'
|
|
4
4
|
require_relative 'jwk/set'
|
5
5
|
|
6
6
|
module JWT
|
7
|
+
# JSON Web Key (JWK)
|
7
8
|
module JWK
|
8
9
|
class << self
|
9
10
|
def create_from(key, params = nil, options = {})
|
@@ -52,4 +53,3 @@ require_relative 'jwk/key_base'
|
|
52
53
|
require_relative 'jwk/ec'
|
53
54
|
require_relative 'jwk/rsa'
|
54
55
|
require_relative 'jwk/hmac'
|
55
|
-
require_relative 'jwk/okp_rbnacl' if JWT.rbnacl?
|
data/lib/jwt/token.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JWT
|
4
|
+
# Represents a JWT token
|
5
|
+
#
|
6
|
+
# Basic token signed using the HS256 algorithm:
|
7
|
+
#
|
8
|
+
# token = JWT::Token.new(payload: {pay: 'load'})
|
9
|
+
# token.sign!(algorithm: 'HS256', key: 'secret')
|
10
|
+
# token.jwt # => eyJhb....
|
11
|
+
#
|
12
|
+
# Custom headers will be combined with generated headers:
|
13
|
+
# token = JWT::Token.new(payload: {pay: 'load'}, header: {custom: "value"})
|
14
|
+
# token.sign!(algorithm: 'HS256', key: 'secret')
|
15
|
+
# token.header # => {"custom"=>"value", "alg"=>"HS256"}
|
16
|
+
#
|
17
|
+
class Token
|
18
|
+
# Initializes a new Token instance.
|
19
|
+
#
|
20
|
+
# @param header [Hash] the header of the JWT token.
|
21
|
+
# @param payload [Hash] the payload of the JWT token.
|
22
|
+
def initialize(payload:, header: {})
|
23
|
+
@header = header&.transform_keys(&:to_s)
|
24
|
+
@payload = payload
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the decoded signature of the JWT token.
|
28
|
+
#
|
29
|
+
# @return [String] the decoded signature of the JWT token.
|
30
|
+
def signature
|
31
|
+
@signature ||= ::JWT::Base64.url_decode(encoded_signature || '')
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the encoded signature of the JWT token.
|
35
|
+
#
|
36
|
+
# @return [String] the encoded signature of the JWT token.
|
37
|
+
def encoded_signature
|
38
|
+
@encoded_signature ||= ::JWT::Base64.url_encode(signature)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns the decoded header of the JWT token.
|
42
|
+
#
|
43
|
+
# @return [Hash] the header of the JWT token.
|
44
|
+
attr_reader :header
|
45
|
+
|
46
|
+
# Returns the encoded header of the JWT token.
|
47
|
+
#
|
48
|
+
# @return [String] the encoded header of the JWT token.
|
49
|
+
def encoded_header
|
50
|
+
@encoded_header ||= ::JWT::Base64.url_encode(JWT::JSON.generate(header))
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns the payload of the JWT token.
|
54
|
+
#
|
55
|
+
# @return [Hash] the payload of the JWT token.
|
56
|
+
attr_reader :payload
|
57
|
+
|
58
|
+
# Returns the encoded payload of the JWT token.
|
59
|
+
#
|
60
|
+
# @return [String] the encoded payload of the JWT token.
|
61
|
+
def encoded_payload
|
62
|
+
@encoded_payload ||= ::JWT::Base64.url_encode(JWT::JSON.generate(payload))
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns the signing input of the JWT token.
|
66
|
+
#
|
67
|
+
# @return [String] the signing input of the JWT token.
|
68
|
+
def signing_input
|
69
|
+
@signing_input ||= [encoded_header, encoded_payload].join('.')
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns the JWT token as a string.
|
73
|
+
#
|
74
|
+
# @return [String] the JWT token as a string.
|
75
|
+
# @raise [JWT::EncodeError] if the token is not signed or other encoding issues
|
76
|
+
def jwt
|
77
|
+
@jwt ||= (@signature && [encoded_header, @detached_payload ? '' : encoded_payload, encoded_signature].join('.')) || raise(::JWT::EncodeError, 'Token is not signed')
|
78
|
+
end
|
79
|
+
|
80
|
+
# Detaches the payload according to https://datatracker.ietf.org/doc/html/rfc7515#appendix-F
|
81
|
+
#
|
82
|
+
def detach_payload!
|
83
|
+
@detached_payload = true
|
84
|
+
|
85
|
+
nil
|
86
|
+
end
|
87
|
+
|
88
|
+
# Signs the JWT token.
|
89
|
+
#
|
90
|
+
# @param key [String, JWT::JWK::KeyBase] the key to use for signing.
|
91
|
+
# @param algorithm [String, Object] the algorithm to use for signing.
|
92
|
+
# @return [void]
|
93
|
+
# @raise [JWT::EncodeError] if the token is already signed or other problems when signing
|
94
|
+
def sign!(key:, algorithm:)
|
95
|
+
raise ::JWT::EncodeError, 'Token already signed' if @signature
|
96
|
+
|
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)
|
100
|
+
end
|
101
|
+
|
102
|
+
nil
|
103
|
+
end
|
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
|
+
|
126
|
+
# Returns the JWT token as a string.
|
127
|
+
#
|
128
|
+
# @return [String] the JWT token as a string.
|
129
|
+
alias to_s jwt
|
130
|
+
end
|
131
|
+
end
|
data/lib/jwt/version.rb
CHANGED
@@ -1,44 +1,49 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
3
|
+
# JSON Web Token implementation
|
4
|
+
#
|
5
|
+
# Should be up to date with the latest spec:
|
6
|
+
# https://tools.ietf.org/html/rfc7519
|
4
7
|
module JWT
|
8
|
+
# Returns the gem version of the JWT library.
|
9
|
+
#
|
10
|
+
# @return [Gem::Version] the gem version.
|
5
11
|
def self.gem_version
|
6
|
-
Gem::Version.new
|
12
|
+
Gem::Version.new(VERSION::STRING)
|
7
13
|
end
|
8
14
|
|
9
|
-
#
|
15
|
+
# Version constants
|
10
16
|
module VERSION
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
MINOR = 8
|
15
|
-
# tiny version
|
16
|
-
TINY = 2
|
17
|
-
# alpha, beta, etc. tag
|
17
|
+
MAJOR = 3
|
18
|
+
MINOR = 1
|
19
|
+
TINY = 1
|
18
20
|
PRE = nil
|
19
21
|
|
20
|
-
# Build version string
|
21
22
|
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
22
23
|
end
|
23
24
|
|
25
|
+
# Checks if the OpenSSL version is 3 or greater.
|
26
|
+
#
|
27
|
+
# @return [Boolean] true if OpenSSL version is 3 or greater, false otherwise.
|
28
|
+
# @api private
|
24
29
|
def self.openssl_3?
|
25
30
|
return false if OpenSSL::OPENSSL_VERSION.include?('LibreSSL')
|
26
31
|
|
27
32
|
true if 3 * 0x10000000 <= OpenSSL::OPENSSL_VERSION_NUMBER
|
28
33
|
end
|
29
34
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
def self.rbnacl_6_or_greater?
|
35
|
-
rbnacl? && ::Gem::Version.new(::RbNaCl::VERSION) >= ::Gem::Version.new('6.0.0')
|
36
|
-
end
|
37
|
-
|
35
|
+
# Checks if there is an OpenSSL 3 HMAC empty key regression.
|
36
|
+
#
|
37
|
+
# @return [Boolean] true if there is an OpenSSL 3 HMAC empty key regression, false otherwise.
|
38
|
+
# @api private
|
38
39
|
def self.openssl_3_hmac_empty_key_regression?
|
39
40
|
openssl_3? && openssl_version <= ::Gem::Version.new('3.0.0')
|
40
41
|
end
|
41
42
|
|
43
|
+
# Returns the OpenSSL version.
|
44
|
+
#
|
45
|
+
# @return [Gem::Version] the OpenSSL version.
|
46
|
+
# @api private
|
42
47
|
def self.openssl_version
|
43
48
|
@openssl_version ||= ::Gem::Version.new(OpenSSL::VERSION)
|
44
49
|
end
|
data/lib/jwt.rb
CHANGED
@@ -5,10 +5,12 @@ 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'
|
11
|
+
require 'jwt/claims'
|
12
|
+
require 'jwt/encoded_token'
|
13
|
+
require 'jwt/token'
|
12
14
|
|
13
15
|
# JSON Web Token implementation
|
14
16
|
#
|
@@ -19,6 +21,13 @@ module JWT
|
|
19
21
|
|
20
22
|
module_function
|
21
23
|
|
24
|
+
# Encodes a payload into a JWT.
|
25
|
+
#
|
26
|
+
# @param payload [Hash] the payload to encode.
|
27
|
+
# @param key [String] the key used to sign the JWT.
|
28
|
+
# @param algorithm [String] the algorithm used to sign the JWT.
|
29
|
+
# @param header_fields [Hash] additional headers to include in the JWT.
|
30
|
+
# @return [String] the encoded JWT.
|
22
31
|
def encode(payload, key, algorithm = 'HS256', header_fields = {})
|
23
32
|
Encode.new(payload: payload,
|
24
33
|
key: key,
|
@@ -26,9 +35,14 @@ module JWT
|
|
26
35
|
headers: header_fields).segments
|
27
36
|
end
|
28
37
|
|
38
|
+
# Decodes a JWT to extract the payload and header
|
39
|
+
#
|
40
|
+
# @param jwt [String] the JWT to decode.
|
41
|
+
# @param key [String] the key used to verify the JWT.
|
42
|
+
# @param verify [Boolean] whether to verify the JWT signature.
|
43
|
+
# @param options [Hash] additional options for decoding.
|
44
|
+
# @return [Array<Hash>] the decoded payload and headers.
|
29
45
|
def decode(jwt, key = nil, verify = true, options = {}, &keyfinder) # rubocop:disable Style/OptionalBooleanParameter
|
30
|
-
|
31
|
-
Decode.new(jwt, key, verify, configuration.decode.to_h.merge(options), &keyfinder).decode_segments
|
32
|
-
end
|
46
|
+
Decode.new(jwt, key, verify, configuration.decode.to_h.merge(options), &keyfinder).decode_segments
|
33
47
|
end
|
34
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,14 +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.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Rudat
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: base64
|
@@ -52,6 +51,34 @@ dependencies:
|
|
52
51
|
- - ">="
|
53
52
|
- !ruby/object:Gem::Version
|
54
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'
|
55
82
|
- !ruby/object:Gem::Dependency
|
56
83
|
name: rake
|
57
84
|
requirement: !ruby/object:Gem::Requirement
|
@@ -121,40 +148,49 @@ files:
|
|
121
148
|
- CONTRIBUTING.md
|
122
149
|
- LICENSE
|
123
150
|
- README.md
|
151
|
+
- UPGRADING.md
|
124
152
|
- lib/jwt.rb
|
125
153
|
- lib/jwt/base64.rb
|
126
|
-
- lib/jwt/
|
154
|
+
- lib/jwt/claims.rb
|
155
|
+
- lib/jwt/claims/audience.rb
|
156
|
+
- lib/jwt/claims/crit.rb
|
157
|
+
- lib/jwt/claims/decode_verifier.rb
|
158
|
+
- lib/jwt/claims/expiration.rb
|
159
|
+
- lib/jwt/claims/issued_at.rb
|
160
|
+
- lib/jwt/claims/issuer.rb
|
161
|
+
- lib/jwt/claims/jwt_id.rb
|
162
|
+
- lib/jwt/claims/not_before.rb
|
163
|
+
- lib/jwt/claims/numeric.rb
|
164
|
+
- lib/jwt/claims/required.rb
|
165
|
+
- lib/jwt/claims/subject.rb
|
166
|
+
- lib/jwt/claims/verifier.rb
|
127
167
|
- lib/jwt/configuration.rb
|
128
168
|
- lib/jwt/configuration/container.rb
|
129
169
|
- lib/jwt/configuration/decode_configuration.rb
|
130
170
|
- lib/jwt/configuration/jwk_configuration.rb
|
131
171
|
- lib/jwt/decode.rb
|
132
|
-
- lib/jwt/deprecations.rb
|
133
172
|
- lib/jwt/encode.rb
|
173
|
+
- lib/jwt/encoded_token.rb
|
134
174
|
- lib/jwt/error.rb
|
135
175
|
- lib/jwt/json.rb
|
136
176
|
- lib/jwt/jwa.rb
|
137
177
|
- lib/jwt/jwa/ecdsa.rb
|
138
|
-
- lib/jwt/jwa/eddsa.rb
|
139
178
|
- lib/jwt/jwa/hmac.rb
|
140
|
-
- lib/jwt/jwa/hmac_rbnacl.rb
|
141
|
-
- lib/jwt/jwa/hmac_rbnacl_fixed.rb
|
142
179
|
- lib/jwt/jwa/none.rb
|
143
180
|
- lib/jwt/jwa/ps.rb
|
144
181
|
- lib/jwt/jwa/rsa.rb
|
182
|
+
- lib/jwt/jwa/signing_algorithm.rb
|
145
183
|
- lib/jwt/jwa/unsupported.rb
|
146
|
-
- lib/jwt/jwa/wrapper.rb
|
147
184
|
- lib/jwt/jwk.rb
|
148
185
|
- lib/jwt/jwk/ec.rb
|
149
186
|
- lib/jwt/jwk/hmac.rb
|
150
187
|
- lib/jwt/jwk/key_base.rb
|
151
188
|
- lib/jwt/jwk/key_finder.rb
|
152
189
|
- lib/jwt/jwk/kid_as_key_digest.rb
|
153
|
-
- lib/jwt/jwk/okp_rbnacl.rb
|
154
190
|
- lib/jwt/jwk/rsa.rb
|
155
191
|
- lib/jwt/jwk/set.rb
|
156
192
|
- lib/jwt/jwk/thumbprint.rb
|
157
|
-
- lib/jwt/
|
193
|
+
- lib/jwt/token.rb
|
158
194
|
- lib/jwt/version.rb
|
159
195
|
- lib/jwt/x5c_key_finder.rb
|
160
196
|
- ruby-jwt.gemspec
|
@@ -163,9 +199,8 @@ licenses:
|
|
163
199
|
- MIT
|
164
200
|
metadata:
|
165
201
|
bug_tracker_uri: https://github.com/jwt/ruby-jwt/issues
|
166
|
-
changelog_uri: https://github.com/jwt/ruby-jwt/blob/
|
202
|
+
changelog_uri: https://github.com/jwt/ruby-jwt/blob/v3.1.1/CHANGELOG.md
|
167
203
|
rubygems_mfa_required: 'true'
|
168
|
-
post_install_message:
|
169
204
|
rdoc_options: []
|
170
205
|
require_paths:
|
171
206
|
- lib
|
@@ -180,8 +215,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
180
215
|
- !ruby/object:Gem::Version
|
181
216
|
version: '0'
|
182
217
|
requirements: []
|
183
|
-
rubygems_version: 3.
|
184
|
-
signing_key:
|
218
|
+
rubygems_version: 3.6.7
|
185
219
|
specification_version: 4
|
186
220
|
summary: JSON Web Token implementation in Ruby
|
187
221
|
test_files: []
|
data/lib/jwt/claims_validator.rb
DELETED
@@ -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
|