jwt 2.4.1 → 2.6.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 +33 -2
- data/CONTRIBUTING.md +7 -7
- data/README.md +135 -31
- data/lib/jwt/algos/algo_wrapper.rb +30 -0
- data/lib/jwt/algos/ecdsa.rb +2 -4
- data/lib/jwt/algos/eddsa.rb +4 -4
- data/lib/jwt/algos/hmac.rb +54 -17
- data/lib/jwt/algos/hmac_rbnacl.rb +53 -0
- data/lib/jwt/algos/hmac_rbnacl_fixed.rb +52 -0
- data/lib/jwt/algos/none.rb +3 -1
- data/lib/jwt/algos/ps.rb +3 -5
- data/lib/jwt/algos/rsa.rb +3 -4
- data/lib/jwt/algos.rb +38 -15
- data/lib/jwt/base64.rb +19 -0
- data/lib/jwt/configuration/container.rb +21 -0
- data/lib/jwt/configuration/decode_configuration.rb +46 -0
- data/lib/jwt/configuration/jwk_configuration.rb +27 -0
- data/lib/jwt/configuration.rb +15 -0
- data/lib/jwt/decode.rb +48 -27
- data/lib/jwt/encode.rb +30 -20
- data/lib/jwt/jwk/ec.rb +131 -62
- data/lib/jwt/jwk/hmac.rb +59 -24
- data/lib/jwt/jwk/key_base.rb +43 -7
- data/lib/jwt/jwk/key_finder.rb +14 -34
- data/lib/jwt/jwk/kid_as_key_digest.rb +15 -0
- data/lib/jwt/jwk/rsa.rb +128 -53
- data/lib/jwt/jwk/set.rb +80 -0
- data/lib/jwt/jwk/thumbprint.rb +26 -0
- data/lib/jwt/jwk.rb +13 -11
- data/lib/jwt/security_utils.rb +0 -27
- data/lib/jwt/version.rb +23 -2
- data/lib/jwt/x5c_key_finder.rb +1 -1
- data/lib/jwt.rb +5 -4
- data/ruby-jwt.gemspec +8 -4
- metadata +15 -30
- data/.codeclimate.yml +0 -8
- data/.github/workflows/coverage.yml +0 -27
- data/.github/workflows/test.yml +0 -66
- data/.gitignore +0 -13
- data/.reek.yml +0 -22
- data/.rspec +0 -2
- data/.rubocop.yml +0 -67
- data/.sourcelevel.yml +0 -17
- data/Appraisals +0 -13
- data/Gemfile +0 -7
- data/Rakefile +0 -16
- data/lib/jwt/default_options.rb +0 -18
- data/lib/jwt/signature.rb +0 -35
data/lib/jwt/jwk/rsa.rb
CHANGED
@@ -2,16 +2,33 @@
|
|
2
2
|
|
3
3
|
module JWT
|
4
4
|
module JWK
|
5
|
-
class RSA < KeyBase
|
5
|
+
class RSA < KeyBase # rubocop:disable Metrics/ClassLength
|
6
6
|
BINARY = 2
|
7
7
|
KTY = 'RSA'
|
8
|
-
KTYS = [KTY, OpenSSL::PKey::RSA].freeze
|
9
|
-
|
8
|
+
KTYS = [KTY, OpenSSL::PKey::RSA, JWT::JWK::RSA].freeze
|
9
|
+
RSA_PUBLIC_KEY_ELEMENTS = %i[kty n e].freeze
|
10
|
+
RSA_PRIVATE_KEY_ELEMENTS = %i[d p q dp dq qi].freeze
|
11
|
+
RSA_KEY_ELEMENTS = (RSA_PRIVATE_KEY_ELEMENTS + RSA_PUBLIC_KEY_ELEMENTS).freeze
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
+
RSA_OPT_PARAMS = %i[p q dp dq qi].freeze
|
14
|
+
RSA_ASN1_SEQUENCE = (%i[n e d] + RSA_OPT_PARAMS).freeze # https://www.rfc-editor.org/rfc/rfc3447#appendix-A.1.2
|
13
15
|
|
14
|
-
|
16
|
+
def initialize(key, params = nil, options = {})
|
17
|
+
params ||= {}
|
18
|
+
|
19
|
+
# For backwards compatibility when kid was a String
|
20
|
+
params = { kid: params } if params.is_a?(String)
|
21
|
+
|
22
|
+
key_params = extract_key_params(key)
|
23
|
+
|
24
|
+
params = params.transform_keys(&:to_sym)
|
25
|
+
check_jwk(key_params, params)
|
26
|
+
|
27
|
+
super(options, key_params.merge(params))
|
28
|
+
end
|
29
|
+
|
30
|
+
def keypair
|
31
|
+
@keypair ||= self.class.create_rsa_key(jwk_attributes(*(RSA_KEY_ELEMENTS - [:kty])))
|
15
32
|
end
|
16
33
|
|
17
34
|
def private?
|
@@ -23,75 +40,124 @@ module JWT
|
|
23
40
|
end
|
24
41
|
|
25
42
|
def export(options = {})
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
e: encode_open_ssl_bn(public_key.e),
|
30
|
-
kid: kid
|
31
|
-
}
|
32
|
-
|
33
|
-
return exported_hash unless private? && options[:include_private] == true
|
34
|
-
|
35
|
-
append_private_parts(exported_hash)
|
43
|
+
exported = parameters.clone
|
44
|
+
exported.reject! { |k, _| RSA_PRIVATE_KEY_ELEMENTS.include? k } unless private? && options[:include_private] == true
|
45
|
+
exported
|
36
46
|
end
|
37
47
|
|
38
|
-
|
48
|
+
def members
|
49
|
+
RSA_PUBLIC_KEY_ELEMENTS.each_with_object({}) { |i, h| h[i] = self[i] }
|
50
|
+
end
|
39
51
|
|
40
|
-
def
|
52
|
+
def key_digest
|
41
53
|
sequence = OpenSSL::ASN1::Sequence([OpenSSL::ASN1::Integer.new(public_key.n),
|
42
54
|
OpenSSL::ASN1::Integer.new(public_key.e)])
|
43
55
|
OpenSSL::Digest::SHA256.hexdigest(sequence.to_der)
|
44
56
|
end
|
45
57
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
58
|
+
def []=(key, value)
|
59
|
+
if RSA_KEY_ELEMENTS.include?(key.to_sym)
|
60
|
+
raise ArgumentError, 'cannot overwrite cryptographic key attributes'
|
61
|
+
end
|
62
|
+
|
63
|
+
super(key, value)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def extract_key_params(key)
|
69
|
+
case key
|
70
|
+
when JWT::JWK::RSA
|
71
|
+
key.export(include_private: true)
|
72
|
+
when OpenSSL::PKey::RSA # Accept OpenSSL key as input
|
73
|
+
@keypair = key # Preserve the object to avoid recreation
|
74
|
+
parse_rsa_key(key)
|
75
|
+
when Hash
|
76
|
+
key.transform_keys(&:to_sym)
|
77
|
+
else
|
78
|
+
raise ArgumentError, 'key must be of type OpenSSL::PKey::RSA or Hash with key parameters'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def check_jwk(keypair, params)
|
83
|
+
raise ArgumentError, 'cannot overwrite cryptographic key attributes' unless (RSA_KEY_ELEMENTS & params.keys).empty?
|
84
|
+
raise JWT::JWKError, "Incorrect 'kty' value: #{keypair[:kty]}, expected #{KTY}" unless keypair[:kty] == KTY
|
85
|
+
raise JWT::JWKError, 'Key format is invalid for RSA' unless keypair[:n] && keypair[:e]
|
86
|
+
end
|
87
|
+
|
88
|
+
def parse_rsa_key(key)
|
89
|
+
{
|
90
|
+
kty: KTY,
|
91
|
+
n: encode_open_ssl_bn(key.n),
|
92
|
+
e: encode_open_ssl_bn(key.e),
|
93
|
+
d: encode_open_ssl_bn(key.d),
|
94
|
+
p: encode_open_ssl_bn(key.p),
|
95
|
+
q: encode_open_ssl_bn(key.q),
|
96
|
+
dp: encode_open_ssl_bn(key.dmp1),
|
97
|
+
dq: encode_open_ssl_bn(key.dmq1),
|
98
|
+
qi: encode_open_ssl_bn(key.iqmp)
|
99
|
+
}.compact
|
100
|
+
end
|
101
|
+
|
102
|
+
def jwk_attributes(*attributes)
|
103
|
+
attributes.each_with_object({}) do |attribute, hash|
|
104
|
+
hash[attribute] = decode_open_ssl_bn(self[attribute])
|
105
|
+
end
|
55
106
|
end
|
56
107
|
|
57
108
|
def encode_open_ssl_bn(key_part)
|
58
|
-
|
109
|
+
return unless key_part
|
110
|
+
|
111
|
+
::JWT::Base64.url_encode(key_part.to_s(BINARY))
|
112
|
+
end
|
113
|
+
|
114
|
+
def decode_open_ssl_bn(jwk_data)
|
115
|
+
self.class.decode_open_ssl_bn(jwk_data)
|
59
116
|
end
|
60
117
|
|
61
118
|
class << self
|
62
119
|
def import(jwk_data)
|
63
|
-
|
64
|
-
decode_open_ssl_bn(value)
|
65
|
-
end
|
66
|
-
kid = jwk_attributes(jwk_data, :kid)[:kid]
|
67
|
-
new(rsa_pkey(pkey_params), kid)
|
120
|
+
new(jwk_data)
|
68
121
|
end
|
69
122
|
|
70
|
-
|
123
|
+
def decode_open_ssl_bn(jwk_data)
|
124
|
+
return nil unless jwk_data
|
71
125
|
|
72
|
-
|
73
|
-
attributes.each_with_object({}) do |attribute, hash|
|
74
|
-
value = jwk_data[attribute] || jwk_data[attribute.to_s]
|
75
|
-
value = yield(value) if block_given?
|
76
|
-
hash[attribute] = value
|
77
|
-
end
|
126
|
+
OpenSSL::BN.new(::JWT::Base64.url_decode(jwk_data), BINARY)
|
78
127
|
end
|
79
128
|
|
80
|
-
def
|
81
|
-
|
129
|
+
def create_rsa_key_using_der(rsa_parameters)
|
130
|
+
validate_rsa_parameters!(rsa_parameters)
|
131
|
+
|
132
|
+
sequence = RSA_ASN1_SEQUENCE.each_with_object([]) do |key, arr|
|
133
|
+
next if rsa_parameters[key].nil?
|
134
|
+
|
135
|
+
arr << OpenSSL::ASN1::Integer.new(rsa_parameters[key])
|
136
|
+
end
|
137
|
+
|
138
|
+
if sequence.size > 2 # Append "two-prime" version for private key
|
139
|
+
sequence.unshift(OpenSSL::ASN1::Integer.new(0))
|
140
|
+
|
141
|
+
raise JWT::JWKError, 'Creating a RSA key with a private key requires the CRT parameters to be defined' if sequence.size < RSA_ASN1_SEQUENCE.size
|
142
|
+
end
|
82
143
|
|
83
|
-
|
144
|
+
OpenSSL::PKey::RSA.new(OpenSSL::ASN1::Sequence(sequence).to_der)
|
84
145
|
end
|
85
146
|
|
86
|
-
|
87
|
-
|
147
|
+
def create_rsa_key_using_sets(rsa_parameters)
|
148
|
+
validate_rsa_parameters!(rsa_parameters)
|
149
|
+
|
150
|
+
OpenSSL::PKey::RSA.new.tap do |rsa_key|
|
88
151
|
rsa_key.set_key(rsa_parameters[:n], rsa_parameters[:e], rsa_parameters[:d])
|
89
152
|
rsa_key.set_factors(rsa_parameters[:p], rsa_parameters[:q]) if rsa_parameters[:p] && rsa_parameters[:q]
|
90
153
|
rsa_key.set_crt_params(rsa_parameters[:dp], rsa_parameters[:dq], rsa_parameters[:qi]) if rsa_parameters[:dp] && rsa_parameters[:dq] && rsa_parameters[:qi]
|
91
|
-
rsa_key
|
92
154
|
end
|
93
|
-
|
94
|
-
|
155
|
+
end
|
156
|
+
|
157
|
+
def create_rsa_key_using_accessors(rsa_parameters) # rubocop:disable Metrics/AbcSize
|
158
|
+
validate_rsa_parameters!(rsa_parameters)
|
159
|
+
|
160
|
+
OpenSSL::PKey::RSA.new.tap do |rsa_key|
|
95
161
|
rsa_key.n = rsa_parameters[:n]
|
96
162
|
rsa_key.e = rsa_parameters[:e]
|
97
163
|
rsa_key.d = rsa_parameters[:d] if rsa_parameters[:d]
|
@@ -100,15 +166,24 @@ module JWT
|
|
100
166
|
rsa_key.dmp1 = rsa_parameters[:dp] if rsa_parameters[:dp]
|
101
167
|
rsa_key.dmq1 = rsa_parameters[:dq] if rsa_parameters[:dq]
|
102
168
|
rsa_key.iqmp = rsa_parameters[:qi] if rsa_parameters[:qi]
|
103
|
-
|
104
|
-
rsa_key
|
105
169
|
end
|
106
170
|
end
|
107
171
|
|
108
|
-
def
|
109
|
-
return
|
172
|
+
def validate_rsa_parameters!(rsa_parameters)
|
173
|
+
return unless rsa_parameters.key?(:d)
|
174
|
+
|
175
|
+
parameters = RSA_OPT_PARAMS - rsa_parameters.keys
|
176
|
+
return if parameters.empty? || parameters.size == RSA_OPT_PARAMS.size
|
110
177
|
|
111
|
-
|
178
|
+
raise JWT::JWKError, 'When one of p, q, dp, dq or qi is given all the other optimization parameters also needs to be defined' # https://www.rfc-editor.org/rfc/rfc7518.html#section-6.3.2
|
179
|
+
end
|
180
|
+
|
181
|
+
if ::JWT.openssl_3?
|
182
|
+
alias create_rsa_key create_rsa_key_using_der
|
183
|
+
elsif OpenSSL::PKey::RSA.new.respond_to?(:set_key)
|
184
|
+
alias create_rsa_key create_rsa_key_using_sets
|
185
|
+
else
|
186
|
+
alias create_rsa_key create_rsa_key_using_accessors
|
112
187
|
end
|
113
188
|
end
|
114
189
|
end
|
data/lib/jwt/jwk/set.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module JWT
|
6
|
+
module JWK
|
7
|
+
class Set
|
8
|
+
include Enumerable
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
attr_reader :keys
|
12
|
+
|
13
|
+
def initialize(jwks = nil, options = {}) # rubocop:disable Metrics/CyclomaticComplexity
|
14
|
+
jwks ||= {}
|
15
|
+
|
16
|
+
@keys = case jwks
|
17
|
+
when JWT::JWK::Set # Simple duplication
|
18
|
+
jwks.keys
|
19
|
+
when JWT::JWK::KeyBase # Singleton
|
20
|
+
[jwks]
|
21
|
+
when Hash
|
22
|
+
jwks = jwks.transform_keys(&:to_sym)
|
23
|
+
[*jwks[:keys]].map { |k| JWT::JWK.new(k, nil, options) }
|
24
|
+
when Array
|
25
|
+
jwks.map { |k| JWT::JWK.new(k, nil, options) }
|
26
|
+
else
|
27
|
+
raise ArgumentError, 'Can only create new JWKS from Hash, Array and JWK'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def export(options = {})
|
32
|
+
{ keys: @keys.map { |k| k.export(options) } }
|
33
|
+
end
|
34
|
+
|
35
|
+
def_delegators :@keys, :each, :size, :delete, :dig
|
36
|
+
|
37
|
+
def select!(&block)
|
38
|
+
return @keys.select! unless block
|
39
|
+
|
40
|
+
self if @keys.select!(&block)
|
41
|
+
end
|
42
|
+
|
43
|
+
def reject!(&block)
|
44
|
+
return @keys.reject! unless block
|
45
|
+
|
46
|
+
self if @keys.reject!(&block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def uniq!(&block)
|
50
|
+
self if @keys.uniq!(&block)
|
51
|
+
end
|
52
|
+
|
53
|
+
def merge(enum)
|
54
|
+
@keys += JWT::JWK::Set.new(enum.to_a).keys
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def union(enum)
|
59
|
+
dup.merge(enum)
|
60
|
+
end
|
61
|
+
|
62
|
+
def add(key)
|
63
|
+
@keys << JWT::JWK.new(key)
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
def ==(other)
|
68
|
+
other.is_a?(JWT::JWK::Set) && keys.sort == other.keys.sort
|
69
|
+
end
|
70
|
+
|
71
|
+
alias eql? ==
|
72
|
+
alias filter! select!
|
73
|
+
alias length size
|
74
|
+
# For symbolic manipulation
|
75
|
+
alias | union
|
76
|
+
alias + union
|
77
|
+
alias << add
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JWT
|
4
|
+
module JWK
|
5
|
+
# https://tools.ietf.org/html/rfc7638
|
6
|
+
class Thumbprint
|
7
|
+
attr_reader :jwk
|
8
|
+
|
9
|
+
def initialize(jwk)
|
10
|
+
@jwk = jwk
|
11
|
+
end
|
12
|
+
|
13
|
+
def generate
|
14
|
+
::Base64.urlsafe_encode64(
|
15
|
+
Digest::SHA256.digest(
|
16
|
+
JWT::JSON.generate(
|
17
|
+
jwk.members.sort.to_h
|
18
|
+
)
|
19
|
+
), padding: false
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
alias to_s generate
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/jwt/jwk.rb
CHANGED
@@ -1,23 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'jwk/key_finder'
|
4
|
+
require_relative 'jwk/set'
|
4
5
|
|
5
6
|
module JWT
|
6
7
|
module JWK
|
7
8
|
class << self
|
8
|
-
def
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
def create_from(key, params = nil, options = {})
|
10
|
+
if key.is_a?(Hash)
|
11
|
+
jwk_kty = key[:kty] || key['kty']
|
12
|
+
raise JWT::JWKError, 'Key type (kty) not provided' unless jwk_kty
|
13
|
+
|
14
|
+
return mappings.fetch(jwk_kty.to_s) do |kty|
|
15
|
+
raise JWT::JWKError, "Key type #{kty} not supported"
|
16
|
+
end.new(key, params, options)
|
17
|
+
end
|
16
18
|
|
17
|
-
|
18
|
-
mappings.fetch(keypair.class) do |klass|
|
19
|
+
mappings.fetch(key.class) do |klass|
|
19
20
|
raise JWT::JWKError, "Cannot create JWK from a #{klass.name}"
|
20
|
-
end.new(
|
21
|
+
end.new(key, params, options)
|
21
22
|
end
|
22
23
|
|
23
24
|
def classes
|
@@ -26,6 +27,7 @@ module JWT
|
|
26
27
|
end
|
27
28
|
|
28
29
|
alias new create_from
|
30
|
+
alias import create_from
|
29
31
|
|
30
32
|
private
|
31
33
|
|
data/lib/jwt/security_utils.rb
CHANGED
@@ -7,17 +7,6 @@ module JWT
|
|
7
7
|
module SecurityUtils
|
8
8
|
module_function
|
9
9
|
|
10
|
-
def secure_compare(left, right)
|
11
|
-
left_bytesize = left.bytesize
|
12
|
-
|
13
|
-
return false unless left_bytesize == right.bytesize
|
14
|
-
|
15
|
-
unpacked_left = left.unpack "C#{left_bytesize}"
|
16
|
-
result = 0
|
17
|
-
right.each_byte { |byte| result |= byte ^ unpacked_left.shift }
|
18
|
-
result.zero?
|
19
|
-
end
|
20
|
-
|
21
10
|
def verify_rsa(algorithm, public_key, signing_input, signature)
|
22
11
|
public_key.verify(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), signature, signing_input)
|
23
12
|
end
|
@@ -39,21 +28,5 @@ module JWT
|
|
39
28
|
sig_char = signature[byte_size..-1] || ''
|
40
29
|
OpenSSL::ASN1::Sequence.new([sig_bytes, sig_char].map { |int| OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(int, 2)) }).to_der
|
41
30
|
end
|
42
|
-
|
43
|
-
def rbnacl_fixup(algorithm, key)
|
44
|
-
algorithm = algorithm.sub('HS', 'SHA').to_sym
|
45
|
-
|
46
|
-
return [] unless defined?(RbNaCl) && RbNaCl::HMAC.constants(false).include?(algorithm)
|
47
|
-
|
48
|
-
authenticator = RbNaCl::HMAC.const_get(algorithm)
|
49
|
-
|
50
|
-
# Fall back to OpenSSL for keys larger than 32 bytes.
|
51
|
-
return [] if key.bytesize > authenticator.key_bytes
|
52
|
-
|
53
|
-
[
|
54
|
-
authenticator,
|
55
|
-
key.bytes.fill(0, key.bytesize...authenticator.key_bytes).pack('C*')
|
56
|
-
]
|
57
|
-
end
|
58
31
|
end
|
59
32
|
end
|
data/lib/jwt/version.rb
CHANGED
@@ -11,13 +11,34 @@ module JWT
|
|
11
11
|
# major version
|
12
12
|
MAJOR = 2
|
13
13
|
# minor version
|
14
|
-
MINOR =
|
14
|
+
MINOR = 6
|
15
15
|
# tiny version
|
16
|
-
TINY =
|
16
|
+
TINY = 0
|
17
17
|
# alpha, beta, etc. tag
|
18
18
|
PRE = nil
|
19
19
|
|
20
20
|
# Build version string
|
21
21
|
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
22
22
|
end
|
23
|
+
|
24
|
+
def self.openssl_3?
|
25
|
+
return false if OpenSSL::OPENSSL_VERSION.include?('LibreSSL')
|
26
|
+
return true if OpenSSL::OPENSSL_VERSION_NUMBER >= 3 * 0x10000000
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.rbnacl?
|
30
|
+
defined?(::RbNaCl)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.rbnacl_6_or_greater?
|
34
|
+
rbnacl? && ::Gem::Version.new(::RbNaCl::VERSION) >= ::Gem::Version.new('6.0.0')
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.openssl_3_hmac_empty_key_regression?
|
38
|
+
openssl_3? && openssl_version <= ::Gem::Version.new('3.0.0')
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.openssl_version
|
42
|
+
@openssl_version ||= ::Gem::Version.new(OpenSSL::VERSION)
|
43
|
+
end
|
23
44
|
end
|
data/lib/jwt/x5c_key_finder.rb
CHANGED
data/lib/jwt.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'jwt/version'
|
4
|
+
require 'jwt/base64'
|
4
5
|
require 'jwt/json'
|
5
6
|
require 'jwt/decode'
|
6
|
-
require 'jwt/
|
7
|
+
require 'jwt/configuration'
|
7
8
|
require 'jwt/encode'
|
8
9
|
require 'jwt/error'
|
9
10
|
require 'jwt/jwk'
|
@@ -13,7 +14,7 @@ require 'jwt/jwk'
|
|
13
14
|
# Should be up to date with the latest spec:
|
14
15
|
# https://tools.ietf.org/html/rfc7519
|
15
16
|
module JWT
|
16
|
-
|
17
|
+
extend ::JWT::Configuration
|
17
18
|
|
18
19
|
module_function
|
19
20
|
|
@@ -25,6 +26,6 @@ module JWT
|
|
25
26
|
end
|
26
27
|
|
27
28
|
def decode(jwt, key = nil, verify = true, options = {}, &keyfinder) # rubocop:disable Style/OptionalBooleanParameter
|
28
|
-
Decode.new(jwt, key, verify,
|
29
|
+
Decode.new(jwt, key, verify, configuration.decode.to_h.merge(options), &keyfinder).decode_segments
|
29
30
|
end
|
30
31
|
end
|
data/ruby-jwt.gemspec
CHANGED
@@ -18,18 +18,22 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.required_ruby_version = '>= 2.5'
|
19
19
|
spec.metadata = {
|
20
20
|
'bug_tracker_uri' => 'https://github.com/jwt/ruby-jwt/issues',
|
21
|
-
'changelog_uri' => "https://github.com/jwt/ruby-jwt/blob/v#{JWT.gem_version}/CHANGELOG.md"
|
21
|
+
'changelog_uri' => "https://github.com/jwt/ruby-jwt/blob/v#{JWT.gem_version}/CHANGELOG.md",
|
22
|
+
'rubygems_mfa_required' => 'true'
|
22
23
|
}
|
23
24
|
|
24
|
-
spec.files = `git ls-files -z`.split("\x0").reject
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
26
|
+
f.match(%r{^(spec|gemfiles|coverage|bin)/}) || # Irrelevant folders
|
27
|
+
f.match(/^\.+/) || # Files and folders starting with .
|
28
|
+
f.match(/^(Appraisals|Gemfile|Rakefile)$/) # Irrelevant files
|
29
|
+
end
|
30
|
+
|
25
31
|
spec.executables = []
|
26
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
27
32
|
spec.require_paths = %w[lib]
|
28
33
|
|
29
34
|
spec.add_development_dependency 'appraisal'
|
30
35
|
spec.add_development_dependency 'bundler'
|
31
36
|
spec.add_development_dependency 'rake'
|
32
|
-
spec.add_development_dependency 'reek'
|
33
37
|
spec.add_development_dependency 'rspec'
|
34
38
|
spec.add_development_dependency 'simplecov'
|
35
39
|
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.
|
4
|
+
version: 2.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Rudat
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-12-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: appraisal
|
@@ -52,20 +52,6 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: reek
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
56
|
name: rspec
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -101,35 +87,31 @@ executables: []
|
|
101
87
|
extensions: []
|
102
88
|
extra_rdoc_files: []
|
103
89
|
files:
|
104
|
-
- ".codeclimate.yml"
|
105
|
-
- ".github/workflows/coverage.yml"
|
106
|
-
- ".github/workflows/test.yml"
|
107
|
-
- ".gitignore"
|
108
|
-
- ".reek.yml"
|
109
|
-
- ".rspec"
|
110
|
-
- ".rubocop.yml"
|
111
|
-
- ".sourcelevel.yml"
|
112
90
|
- AUTHORS
|
113
|
-
- Appraisals
|
114
91
|
- CHANGELOG.md
|
115
92
|
- CODE_OF_CONDUCT.md
|
116
93
|
- CONTRIBUTING.md
|
117
|
-
- Gemfile
|
118
94
|
- LICENSE
|
119
95
|
- README.md
|
120
|
-
- Rakefile
|
121
96
|
- lib/jwt.rb
|
122
97
|
- lib/jwt/algos.rb
|
98
|
+
- lib/jwt/algos/algo_wrapper.rb
|
123
99
|
- lib/jwt/algos/ecdsa.rb
|
124
100
|
- lib/jwt/algos/eddsa.rb
|
125
101
|
- lib/jwt/algos/hmac.rb
|
102
|
+
- lib/jwt/algos/hmac_rbnacl.rb
|
103
|
+
- lib/jwt/algos/hmac_rbnacl_fixed.rb
|
126
104
|
- lib/jwt/algos/none.rb
|
127
105
|
- lib/jwt/algos/ps.rb
|
128
106
|
- lib/jwt/algos/rsa.rb
|
129
107
|
- lib/jwt/algos/unsupported.rb
|
108
|
+
- lib/jwt/base64.rb
|
130
109
|
- lib/jwt/claims_validator.rb
|
110
|
+
- lib/jwt/configuration.rb
|
111
|
+
- lib/jwt/configuration/container.rb
|
112
|
+
- lib/jwt/configuration/decode_configuration.rb
|
113
|
+
- lib/jwt/configuration/jwk_configuration.rb
|
131
114
|
- lib/jwt/decode.rb
|
132
|
-
- lib/jwt/default_options.rb
|
133
115
|
- lib/jwt/encode.rb
|
134
116
|
- lib/jwt/error.rb
|
135
117
|
- lib/jwt/json.rb
|
@@ -138,9 +120,11 @@ files:
|
|
138
120
|
- lib/jwt/jwk/hmac.rb
|
139
121
|
- lib/jwt/jwk/key_base.rb
|
140
122
|
- lib/jwt/jwk/key_finder.rb
|
123
|
+
- lib/jwt/jwk/kid_as_key_digest.rb
|
141
124
|
- lib/jwt/jwk/rsa.rb
|
125
|
+
- lib/jwt/jwk/set.rb
|
126
|
+
- lib/jwt/jwk/thumbprint.rb
|
142
127
|
- lib/jwt/security_utils.rb
|
143
|
-
- lib/jwt/signature.rb
|
144
128
|
- lib/jwt/verify.rb
|
145
129
|
- lib/jwt/version.rb
|
146
130
|
- lib/jwt/x5c_key_finder.rb
|
@@ -150,7 +134,8 @@ licenses:
|
|
150
134
|
- MIT
|
151
135
|
metadata:
|
152
136
|
bug_tracker_uri: https://github.com/jwt/ruby-jwt/issues
|
153
|
-
changelog_uri: https://github.com/jwt/ruby-jwt/blob/v2.
|
137
|
+
changelog_uri: https://github.com/jwt/ruby-jwt/blob/v2.6.0/CHANGELOG.md
|
138
|
+
rubygems_mfa_required: 'true'
|
154
139
|
post_install_message:
|
155
140
|
rdoc_options: []
|
156
141
|
require_paths:
|
data/.codeclimate.yml
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
---
|
2
|
-
name: coverage
|
3
|
-
on:
|
4
|
-
push:
|
5
|
-
branches:
|
6
|
-
- "master"
|
7
|
-
jobs:
|
8
|
-
coverage:
|
9
|
-
name: coverage
|
10
|
-
runs-on: ubuntu-20.04
|
11
|
-
env:
|
12
|
-
BUNDLE_GEMFILE: 'gemfiles/rbnacl.gemfile'
|
13
|
-
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
14
|
-
steps:
|
15
|
-
- uses: actions/checkout@v2
|
16
|
-
- name: Install libsodium
|
17
|
-
run: |
|
18
|
-
sudo apt-get update -q
|
19
|
-
sudo apt-get install libsodium-dev -y
|
20
|
-
- name: Set up Ruby
|
21
|
-
uses: ruby/setup-ruby@v1
|
22
|
-
with:
|
23
|
-
ruby-version: "2.7"
|
24
|
-
bundler-cache: true
|
25
|
-
- uses: paambaati/codeclimate-action@v3.0.0
|
26
|
-
with:
|
27
|
-
coverageCommand: bundle exec rspec
|