jwt 1.5.6 → 2.2.2
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 +5 -5
- data/.ebert.yml +18 -0
- data/.gitignore +1 -1
- data/.rubocop.yml +96 -0
- data/.travis.yml +26 -10
- data/AUTHORS +84 -0
- data/Appraisals +18 -0
- data/CHANGELOG.md +296 -10
- data/Gemfile +0 -1
- data/README.md +182 -64
- data/lib/jwt.rb +14 -176
- data/lib/jwt/algos/ecdsa.rb +35 -0
- data/lib/jwt/algos/eddsa.rb +23 -0
- data/lib/jwt/algos/hmac.rb +34 -0
- data/lib/jwt/algos/ps.rb +43 -0
- data/lib/jwt/algos/rsa.rb +19 -0
- data/lib/jwt/algos/unsupported.rb +16 -0
- data/lib/jwt/base64.rb +19 -0
- data/lib/jwt/claims_validator.rb +33 -0
- data/lib/jwt/decode.rb +81 -31
- data/lib/jwt/default_options.rb +15 -0
- data/lib/jwt/encode.rb +68 -0
- data/lib/jwt/error.rb +6 -0
- data/lib/jwt/json.rb +10 -9
- data/lib/jwt/jwk.rb +31 -0
- data/lib/jwt/jwk/key_finder.rb +57 -0
- data/lib/jwt/jwk/rsa.rb +54 -0
- data/lib/jwt/security_utils.rb +57 -0
- data/lib/jwt/signature.rb +54 -0
- data/lib/jwt/verify.rb +45 -53
- data/lib/jwt/version.rb +3 -3
- data/ruby-jwt.gemspec +11 -7
- metadata +76 -67
- data/Manifest +0 -8
- data/spec/fixtures/certs/ec256-private.pem +0 -8
- data/spec/fixtures/certs/ec256-public.pem +0 -4
- data/spec/fixtures/certs/ec256-wrong-private.pem +0 -8
- data/spec/fixtures/certs/ec256-wrong-public.pem +0 -4
- data/spec/fixtures/certs/ec384-private.pem +0 -9
- data/spec/fixtures/certs/ec384-public.pem +0 -5
- data/spec/fixtures/certs/ec384-wrong-private.pem +0 -9
- data/spec/fixtures/certs/ec384-wrong-public.pem +0 -5
- data/spec/fixtures/certs/ec512-private.pem +0 -10
- data/spec/fixtures/certs/ec512-public.pem +0 -6
- data/spec/fixtures/certs/ec512-wrong-private.pem +0 -10
- data/spec/fixtures/certs/ec512-wrong-public.pem +0 -6
- data/spec/fixtures/certs/rsa-1024-private.pem +0 -15
- data/spec/fixtures/certs/rsa-1024-public.pem +0 -6
- data/spec/fixtures/certs/rsa-2048-private.pem +0 -27
- data/spec/fixtures/certs/rsa-2048-public.pem +0 -9
- data/spec/fixtures/certs/rsa-2048-wrong-private.pem +0 -27
- data/spec/fixtures/certs/rsa-2048-wrong-public.pem +0 -9
- data/spec/fixtures/certs/rsa-4096-private.pem +0 -51
- data/spec/fixtures/certs/rsa-4096-public.pem +0 -14
- data/spec/integration/readme_examples_spec.rb +0 -190
- data/spec/jwt/verify_spec.rb +0 -197
- data/spec/jwt_spec.rb +0 -240
- data/spec/spec_helper.rb +0 -31
data/spec/jwt_spec.rb
DELETED
@@ -1,240 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'jwt'
|
3
|
-
require 'jwt/decode'
|
4
|
-
|
5
|
-
describe JWT do
|
6
|
-
let(:payload) { { 'user_id' => 'some@user.tld' } }
|
7
|
-
|
8
|
-
let :data do
|
9
|
-
{
|
10
|
-
:secret => 'My$ecretK3y',
|
11
|
-
:rsa_private => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-private.pem'))),
|
12
|
-
:rsa_public => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-public.pem'))),
|
13
|
-
:wrong_rsa_private => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-wrong-public.pem'))),
|
14
|
-
:wrong_rsa_public => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-wrong-public.pem'))),
|
15
|
-
'ES256_private' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec256-private.pem'))),
|
16
|
-
'ES256_public' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec256-public.pem'))),
|
17
|
-
'ES384_private' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec384-private.pem'))),
|
18
|
-
'ES384_public' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec384-public.pem'))),
|
19
|
-
'ES512_private' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec512-private.pem'))),
|
20
|
-
'ES512_public' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec512-public.pem'))),
|
21
|
-
'NONE' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.',
|
22
|
-
'HS256' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.tCGvlClld0lbQ3NZaH8y53n5RSBr3zlS4Oy5bXqvzZQ',
|
23
|
-
'HS384' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.sj1gc01SawlJSrPZgmveifJ8CzZRYAWjejWm4FRaGaAISESJ9Ncf12fCz2vHrITm',
|
24
|
-
'HS512' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.isjhsWMZpRQOWw6LKtlY4L6tMDNkLr0qZ3bQe_xRFXWhzVvJlkclTbLVa1J6Dlj2WyZ_I1jEobTaFMDoXPzwWg',
|
25
|
-
'RS256' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.u82QrhjZTtwve5akvfWS_4LPywbkb1Yp0nUwZJWtTW0ID7dY9rRiQF5KGj2UDLZotqRlUjyNQgE_hB5BBzICDQdCjQHQoYWE5n_D2wV4PMu7Qg3FVKoBFbf8ee6irodu10fgYxpUIZtvbWw52_6k6A9IoSLSzx_lCcxoVGdW90dUuKhBcZkDtY5WNuQg7MiDthupSL1-V4Y1jmT_7o8tLNGFiocyZfGNw4yGpEOGNvD5WePNit0xsnbj6dEquovUvSFKsMaQXp2PVDEkLOiLMcyk0RrHqrHw2eNSCquWTH8PhX5Up-CVmjQM5zF9ibkaiq8NyPtsy-7rgtbyVMqXBQ',
|
26
|
-
'RS384' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzM4NCJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.2_jPwOsUWJ-3r6lXMdJGPdhLNJQSSEmY2mrDXCwNJk-2YhMIqKAzJJCbyso_A1hS7BVkXmHt54RCcNJXroZBOgmGavCcYTPMaT6sCvVVvJJ_wn7jzKHNAJfL5nWeynTQIBWmL-m_v9QpZAgPALdeqjPRv4JHePZm23kvrUgQOxef2ldXv1l6IB3zfF72uEbk9T5pKBvgeeeQ46xm_HtkpXqMdqcTHawUXeXhuiWxuWfy9pAvhm8ivxwJhiQ15-sQNBlS9lG1_gQz1xaZ_Ou_n1nhNfGwpK5HeS0AgmqsqyCOvaGHeAuAOPZ_dSC3cFKu2AP7kc6_AKBgwJzh4agkXg',
|
27
|
-
'RS512' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.abwof7BqTvuLkN69OhEuFTP7vjGzfvAvooQdwIRne_a88MsjCq31n4UPvyIlY9_8u69rpU79RbMsrq_UZ6L85zP83EcyYI-HOfFZgYDAL3DJ7biBD99JTzyOsH_2i_E6yCkevjEX6uL_Am_C7jpWyePJQkYzTFni6mW4W1T9UobiVGA1tIZ-XOJDPHHxZkGu6W8lKW0UCsr9Ge2SCSlTs_LDSOa34gqMC5GP89unhLqSMqEMJ_Nm6Rj0rnmk87wBZM-b04LLteWuEU59QDNa4nMTjfXW74U4hX9n5EECDPQdQMecgxlUbFunAfZaoNzP4m7H4vux2FzYkjkXhdqnnw',
|
28
|
-
'ES256' => '',
|
29
|
-
'ES384' => '',
|
30
|
-
'ES512' => ''
|
31
|
-
}
|
32
|
-
end
|
33
|
-
|
34
|
-
after(:each) do
|
35
|
-
expect(OpenSSL.errors).to be_empty
|
36
|
-
end
|
37
|
-
|
38
|
-
context 'alg: NONE' do
|
39
|
-
let(:alg) { 'none' }
|
40
|
-
|
41
|
-
it 'should generate a valid token' do
|
42
|
-
token = JWT.encode payload, nil, alg
|
43
|
-
|
44
|
-
expect(token).to eq data['NONE']
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'should decode a valid token' do
|
48
|
-
jwt_payload, header = JWT.decode data['NONE'], nil, false
|
49
|
-
|
50
|
-
expect(header['alg']).to eq alg
|
51
|
-
expect(jwt_payload).to eq payload
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'should display a better error message if payload exp is_a?(Time)' do
|
55
|
-
payload['exp'] = Time.now
|
56
|
-
|
57
|
-
expect do
|
58
|
-
JWT.encode payload, nil, alg
|
59
|
-
end.to raise_error JWT::InvalidPayload
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
%w(HS256 HS384 HS512).each do |alg|
|
64
|
-
context "alg: #{alg}" do
|
65
|
-
it 'should generate a valid token' do
|
66
|
-
token = JWT.encode payload, data[:secret], alg
|
67
|
-
|
68
|
-
expect(token).to eq data[alg]
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'should decode a valid token' do
|
72
|
-
jwt_payload, header = JWT.decode data[alg], data[:secret]
|
73
|
-
|
74
|
-
expect(header['alg']).to eq alg
|
75
|
-
expect(jwt_payload).to eq payload
|
76
|
-
end
|
77
|
-
|
78
|
-
it 'wrong secret should raise JWT::DecodeError' do
|
79
|
-
expect do
|
80
|
-
JWT.decode data[alg], 'wrong_secret'
|
81
|
-
end.to raise_error JWT::DecodeError
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'wrong secret and verify = false should not raise JWT::DecodeError' do
|
85
|
-
expect do
|
86
|
-
JWT.decode data[alg], 'wrong_secret', false
|
87
|
-
end.not_to raise_error
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
%w(RS256 RS384 RS512).each do |alg|
|
93
|
-
context "alg: #{alg}" do
|
94
|
-
it 'should generate a valid token' do
|
95
|
-
token = JWT.encode payload, data[:rsa_private], alg
|
96
|
-
|
97
|
-
expect(token).to eq data[alg]
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'should decode a valid token' do
|
101
|
-
jwt_payload, header = JWT.decode data[alg], data[:rsa_public]
|
102
|
-
|
103
|
-
expect(header['alg']).to eq alg
|
104
|
-
expect(jwt_payload).to eq payload
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'wrong key should raise JWT::DecodeError' do
|
108
|
-
key = OpenSSL::PKey.read File.read(File.join(CERT_PATH, 'rsa-2048-wrong-public.pem'))
|
109
|
-
|
110
|
-
expect do
|
111
|
-
JWT.decode data[alg], key
|
112
|
-
end.to raise_error JWT::DecodeError
|
113
|
-
end
|
114
|
-
|
115
|
-
it 'wrong key and verify = false should not raise JWT::DecodeError' do
|
116
|
-
key = OpenSSL::PKey.read File.read(File.join(CERT_PATH, 'rsa-2048-wrong-public.pem'))
|
117
|
-
|
118
|
-
expect do
|
119
|
-
JWT.decode data[alg], key, false
|
120
|
-
end.not_to raise_error
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
%w(ES256 ES384 ES512).each do |alg|
|
126
|
-
context "alg: #{alg}" do
|
127
|
-
before(:each) do
|
128
|
-
data[alg] = JWT.encode payload, data["#{alg}_private"], alg
|
129
|
-
end
|
130
|
-
|
131
|
-
let(:wrong_key) { OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec256-wrong-public.pem'))) }
|
132
|
-
|
133
|
-
it 'should generate a valid token' do
|
134
|
-
jwt_payload, header = JWT.decode data[alg], data["#{alg}_public"]
|
135
|
-
|
136
|
-
expect(header['alg']).to eq alg
|
137
|
-
expect(jwt_payload).to eq payload
|
138
|
-
end
|
139
|
-
|
140
|
-
it 'should decode a valid token' do
|
141
|
-
jwt_payload, header = JWT.decode data[alg], data["#{alg}_public"]
|
142
|
-
|
143
|
-
expect(header['alg']).to eq alg
|
144
|
-
expect(jwt_payload).to eq payload
|
145
|
-
end
|
146
|
-
|
147
|
-
it 'wrong key should raise JWT::DecodeError' do
|
148
|
-
expect do
|
149
|
-
JWT.decode data[alg], wrong_key
|
150
|
-
end.to raise_error JWT::DecodeError
|
151
|
-
end
|
152
|
-
|
153
|
-
it 'wrong key and verify = false should not raise JWT::DecodeError' do
|
154
|
-
expect do
|
155
|
-
JWT.decode data[alg], wrong_key, false
|
156
|
-
end.not_to raise_error
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
context 'Invalid' do
|
162
|
-
it 'algorithm should raise NotImplementedError' do
|
163
|
-
expect do
|
164
|
-
JWT.encode payload, 'secret', 'HS255'
|
165
|
-
end.to raise_error NotImplementedError
|
166
|
-
end
|
167
|
-
|
168
|
-
it 'ECDSA curve_name should raise JWT::IncorrectAlgorithm' do
|
169
|
-
key = OpenSSL::PKey::EC.new 'secp256k1'
|
170
|
-
key.generate_key
|
171
|
-
|
172
|
-
expect do
|
173
|
-
JWT.encode payload, key, 'ES256'
|
174
|
-
end.to raise_error JWT::IncorrectAlgorithm
|
175
|
-
|
176
|
-
token = JWT.encode payload, data['ES256_private'], 'ES256'
|
177
|
-
key.private_key = nil
|
178
|
-
|
179
|
-
expect do
|
180
|
-
JWT.decode token, key
|
181
|
-
end.to raise_error JWT::IncorrectAlgorithm
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
context 'Verify' do
|
186
|
-
context 'algorithm' do
|
187
|
-
it 'should raise JWT::IncorrectAlgorithm on missmatch' do
|
188
|
-
token = JWT.encode payload, data[:secret], 'HS512'
|
189
|
-
|
190
|
-
expect do
|
191
|
-
JWT.decode token, data[:secret], true, algorithm: 'HS384'
|
192
|
-
end.to raise_error JWT::IncorrectAlgorithm
|
193
|
-
|
194
|
-
expect do
|
195
|
-
JWT.decode token, data[:secret], true, algorithm: 'HS512'
|
196
|
-
end.not_to raise_error
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
context 'issuer claim' do
|
201
|
-
let(:iss) { 'ruby-jwt-gem' }
|
202
|
-
let(:invalid_token) { JWT.encode payload, data[:secret] }
|
203
|
-
|
204
|
-
let :token do
|
205
|
-
iss_payload = payload.merge(iss: iss)
|
206
|
-
JWT.encode iss_payload, data[:secret]
|
207
|
-
end
|
208
|
-
|
209
|
-
it 'if verify_iss is set to false (default option) should not raise JWT::InvalidIssuerError' do
|
210
|
-
expect do
|
211
|
-
JWT.decode token, data[:secret], true, iss: iss
|
212
|
-
end.not_to raise_error
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
context 'Base64' do
|
218
|
-
it 'urlsafe replace + / with - _' do
|
219
|
-
allow(Base64).to receive(:encode64) { 'string+with/non+url-safe/characters_' }
|
220
|
-
expect(JWT.base64url_encode('foo')).to eq('string-with_non-url-safe_characters_')
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
describe 'secure comparison' do
|
225
|
-
it 'returns true if strings are equal' do
|
226
|
-
expect(JWT.secure_compare('Foo', 'Foo')).to eq true
|
227
|
-
end
|
228
|
-
|
229
|
-
it 'returns false if either input is nil or empty' do
|
230
|
-
[nil, ''].each do |bad|
|
231
|
-
expect(JWT.secure_compare(bad, 'Foo')).to eq false
|
232
|
-
expect(JWT.secure_compare('Foo', bad)).to eq false
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
it 'retuns false if the strings are different' do
|
237
|
-
expect(JWT.secure_compare('Foo', 'Bar')).to eq false
|
238
|
-
end
|
239
|
-
end
|
240
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'rspec'
|
2
|
-
require 'simplecov'
|
3
|
-
require 'simplecov-json'
|
4
|
-
require 'codeclimate-test-reporter'
|
5
|
-
|
6
|
-
SimpleCov.configure do
|
7
|
-
root File.join(File.dirname(__FILE__), '..')
|
8
|
-
project_name 'Ruby JWT - Ruby JSON Web Token implementation'
|
9
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
|
10
|
-
SimpleCov::Formatter::HTMLFormatter,
|
11
|
-
SimpleCov::Formatter::JSONFormatter
|
12
|
-
])
|
13
|
-
|
14
|
-
add_filter 'spec'
|
15
|
-
end
|
16
|
-
|
17
|
-
SimpleCov.start if ENV['COVERAGE']
|
18
|
-
CodeClimate::TestReporter.start if ENV['CODECLIMATE_REPO_TOKEN']
|
19
|
-
|
20
|
-
CERT_PATH = File.join(File.dirname(__FILE__), 'fixtures', 'certs')
|
21
|
-
|
22
|
-
RSpec.configure do |config|
|
23
|
-
config.expect_with :rspec do |c|
|
24
|
-
c.syntax = [:should, :expect]
|
25
|
-
end
|
26
|
-
|
27
|
-
config.run_all_when_everything_filtered = true
|
28
|
-
config.filter_run :focus
|
29
|
-
|
30
|
-
config.order = 'random'
|
31
|
-
end
|