json-jwt 1.9.1 → 1.17.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.
@@ -1,496 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe JSON::JWT do
4
- let(:jwt) { JSON::JWT.new claims }
5
- let(:jws) do
6
- jwt.alg = :HS256
7
- jws = JSON::JWS.new jwt
8
- jws.signature = 'signature'
9
- jws
10
- end
11
- let(:claims) do
12
- {
13
- iss: 'joe',
14
- exp: 1300819380,
15
- 'http://example.com/is_root' => true
16
- }.with_indifferent_access
17
- end
18
- let(:no_signed) do
19
- 'eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.'
20
- end
21
-
22
- context 'when not signed nor encrypted' do
23
- it do
24
- jwt.to_s.should == no_signed
25
- end
26
- end
27
-
28
- describe '#content_type' do
29
- it do
30
- jwt.content_type.should == 'application/jwt'
31
- end
32
- end
33
-
34
- describe '#sign' do
35
- [:HS256, :HS384, :HS512].each do |algorithm|
36
- context algorithm do
37
- it do
38
- jwt.sign(shared_secret, algorithm).should be_a JSON::JWS
39
- end
40
- end
41
- end
42
-
43
- [:RS256, :RS384, :RS512].each do |algorithm|
44
- context algorithm do
45
- it do
46
- jwt.sign(private_key, algorithm).should be_a JSON::JWS
47
- end
48
- end
49
- end
50
-
51
- context 'when no algirithm specified' do
52
- subject { jwt.sign(key) }
53
-
54
- context 'when key is String' do
55
- let(:key) { shared_secret }
56
- its(:alg) { should == :HS256 }
57
- end
58
-
59
- context 'when key is RSA key' do
60
- let(:key) { private_key }
61
- its(:alg) { should == :RS256 }
62
- end
63
-
64
- context 'when key is EC key' do
65
- context 'when prime256v1' do
66
- let(:key) { private_key(:ecdsa) }
67
- its(:alg) { should == :ES256 }
68
- end
69
-
70
- context 'when secp384r1' do
71
- let(:key) { private_key(:ecdsa, digest_length: 384) }
72
- its(:alg) { should == :ES384 }
73
- end
74
-
75
- context 'when secp521r1' do
76
- let(:key) { private_key(:ecdsa, digest_length: 512) }
77
- its(:alg) { should == :ES512 }
78
- end
79
- end
80
- end
81
-
82
- context 'when non-JWK key is given' do
83
- let(:key) { private_key }
84
- it 'should not set kid header automatically' do
85
- jws = jwt.sign(key, :RS256)
86
- jws.kid.should be_blank
87
- end
88
- end
89
-
90
- context 'when JWK is given' do
91
- let(:key) { JSON::JWK.new private_key }
92
- it 'should set kid header automatically' do
93
- jws = jwt.sign(key, :RS256)
94
- jwt.kid.should be_blank
95
- jws.kid.should == key[:kid]
96
- end
97
- end
98
-
99
- describe 'object copy behaviour' do
100
- before do
101
- @jwt = JSON::JWT.new(obj: {foo: :bar})
102
- @jws = @jwt.sign('secret')
103
- end
104
-
105
- context 'when original JWT is modified' do
106
- before do
107
- @jwt.header[:x] = :x
108
- @jwt[:obj][:x] = :x
109
- end
110
-
111
- describe 'copied JWS' do
112
- it 'should be affected as shallow copy, but not as a simple reference' do
113
- @jws.header.should_not include :x
114
- @jws[:obj].should include :x
115
- end
116
- end
117
- end
118
-
119
- context 'when copied JWS is modified' do
120
- before do
121
- @jws.header[:x] = :x
122
- @jws[:obj][:x] = :x
123
- end
124
-
125
- describe 'original JWT' do
126
- it 'should be affected as shallow copy, but not as a simple reference' do
127
- @jwt.header.should_not include :x
128
- @jwt[:obj].should include :x
129
- end
130
- end
131
- end
132
- end
133
- end
134
-
135
- describe '#encrypt' do
136
- let(:shared_key) { SecureRandom.hex 16 } # default shared key is too short
137
-
138
- it 'should encryptable without signing' do
139
- jwt.encrypt(public_key).should be_a JSON::JWE
140
- end
141
-
142
- it 'should encryptable after signed' do
143
- jwt.sign(shared_key).encrypt(public_key).should be_a JSON::JWE
144
- end
145
-
146
- it 'should accept optional algorithm' do
147
- jwt.encrypt(shared_key, :dir).should be_a JSON::JWE
148
- end
149
-
150
- it 'should accept optional algorithm and encryption method' do
151
- jwt.encrypt(SecureRandom.hex(32), :dir, :'A256CBC-HS512').should be_a JSON::JWE
152
- end
153
-
154
- context 'when non-JWK key is given' do
155
- let(:key) { shared_key }
156
- it 'should not set kid header automatically' do
157
- jwe = jwt.encrypt(key, :dir)
158
- jwe.kid.should be_blank
159
- end
160
- end
161
-
162
- context 'when JWK is given' do
163
- let(:key) { JSON::JWK.new shared_key }
164
- it 'should set kid header automatically' do
165
- jwe = jwt.encrypt(key, :dir)
166
- jwt.kid.should be_blank
167
- jwe.kid.should == key[:kid]
168
- end
169
- end
170
- end
171
-
172
- describe '.decode' do
173
- context 'when not signed nor encrypted' do
174
- context 'no signature given' do
175
- it do
176
- JSON::JWT.decode(no_signed).should == jwt
177
- end
178
- end
179
- end
180
-
181
- context 'when signed' do
182
- context 'when no secret/key given' do
183
- it 'should do verification' do
184
- expect do
185
- JSON::JWT.decode jws.to_s
186
- end.to raise_error JSON::JWT::VerificationFailed
187
- end
188
- end
189
-
190
- context 'when secret/key given' do
191
- it 'should do verification' do
192
- expect do
193
- JSON::JWT.decode jws.to_s, 'secret'
194
- end.to raise_error JSON::JWT::VerificationFailed
195
- end
196
- end
197
-
198
- context 'when alg header malformed' do
199
- context 'from alg=HS256' do
200
- context 'to alg=none' do
201
- let(:malformed_jwt_string) do
202
- header, payload, signature = jws.to_s.split('.')
203
- malformed_header = {alg: :none}.to_json
204
- [
205
- UrlSafeBase64.encode64(malformed_header),
206
- payload,
207
- ''
208
- ].join('.')
209
- end
210
-
211
- it do
212
- expect do
213
- JSON::JWT.decode malformed_jwt_string, 'secret'
214
- end.to raise_error JSON::JWT::VerificationFailed
215
- end
216
- end
217
- end
218
-
219
- context 'from alg=RS256' do
220
- let(:jws) do
221
- jwt.sign private_key, :RS256
222
- end
223
-
224
- context 'to alg=none' do
225
- let(:malformed_jwt_string) do
226
- header, payload, signature = jws.to_s.split('.')
227
- malformed_header = {alg: :none}.to_json
228
- [
229
- UrlSafeBase64.encode64(malformed_header),
230
- payload,
231
- ''
232
- ].join('.')
233
- end
234
-
235
- it do
236
- expect do
237
- JSON::JWT.decode malformed_jwt_string, public_key
238
- end.to raise_error JSON::JWT::UnexpectedAlgorithm
239
- end
240
- end
241
-
242
- context 'to alg=HS256' do
243
- let(:malformed_jwt_string) do
244
- header, payload, signature = jws.to_s.split('.')
245
- malformed_header = {alg: :HS256}.to_json
246
- malformed_signature = OpenSSL::HMAC.digest(
247
- OpenSSL::Digest.new('SHA256'),
248
- public_key.to_s,
249
- [UrlSafeBase64.encode64(malformed_header), payload].join('.')
250
- )
251
- [
252
- UrlSafeBase64.encode64(malformed_header),
253
- payload,
254
- UrlSafeBase64.encode64(malformed_signature)
255
- ].join('.')
256
- end
257
-
258
- it do
259
- expect do
260
- JSON::JWT.decode malformed_jwt_string, public_key
261
- end.to raise_error JSON::JWS::UnexpectedAlgorithm
262
- end
263
- end
264
- end
265
-
266
- context 'from alg=PS512' do
267
- let(:jws) do
268
- jwt.sign private_key, :PS512
269
- end
270
-
271
- if pss_supported?
272
- context 'to alg=PS256' do
273
- let(:malformed_jwt_string) do
274
- header, payload, signature = jws.to_s.split('.')
275
- malformed_header = {alg: :PS256}.to_json
276
- digest = OpenSSL::Digest.new('SHA256')
277
- malformed_signature = private_key.sign_pss(
278
- digest,
279
- [UrlSafeBase64.encode64(malformed_header), payload].join('.'),
280
- salt_length: :digest,
281
- mgf1_hash: digest
282
- )
283
- [
284
- UrlSafeBase64.encode64(malformed_header),
285
- payload,
286
- UrlSafeBase64.encode64(malformed_signature)
287
- ].join('.')
288
- end
289
-
290
- context 'when verification algorithm is specified' do
291
- it do
292
- expect do
293
- JSON::JWT.decode malformed_jwt_string, public_key, :PS512
294
- end.to raise_error JSON::JWS::UnexpectedAlgorithm, 'Unexpected alg header'
295
- end
296
- end
297
-
298
- context 'otherwise' do
299
- it do
300
- expect do
301
- JSON::JWT.decode malformed_jwt_string, public_key
302
- end.not_to raise_error
303
- end
304
- end
305
- end
306
-
307
- context 'to alg=RS516' do
308
- let(:malformed_jwt_string) do
309
- header, payload, signature = jws.to_s.split('.')
310
- malformed_header = {alg: :RS512}.to_json
311
- malformed_signature = private_key.sign(
312
- OpenSSL::Digest.new('SHA512'),
313
- [UrlSafeBase64.encode64(malformed_header), payload].join('.')
314
- )
315
- [
316
- UrlSafeBase64.encode64(malformed_header),
317
- payload,
318
- UrlSafeBase64.encode64(malformed_signature)
319
- ].join('.')
320
- end
321
-
322
- context 'when verification algorithm is specified' do
323
- it do
324
- expect do
325
- JSON::JWT.decode malformed_jwt_string, public_key, :PS512
326
- end.to raise_error JSON::JWS::UnexpectedAlgorithm, 'Unexpected alg header'
327
- end
328
- end
329
-
330
- context 'otherwise' do
331
- it do
332
- expect do
333
- JSON::JWT.decode malformed_jwt_string, public_key
334
- end.not_to raise_error
335
- end
336
- end
337
- end
338
- else
339
- skip 'RSA PSS not supported'
340
- it do
341
- expect { jws }.to raise_error 'PS512 isn\'t supported. OpenSSL gem v2.1.0+ is required to use PS512.'
342
- end
343
- end
344
- end
345
- end
346
-
347
- context 'when :skip_verification given as secret/key' do
348
- it 'should skip verification' do
349
- expect do
350
- jwt = JSON::JWT.decode jws.to_s, :skip_verification
351
- jwt.header.should == {'alg' => 'HS256', 'typ' => 'JWT'}
352
- end.not_to raise_error
353
- end
354
- end
355
-
356
- context 'when JSON Serialization given' do
357
- let(:signed) { JSON::JWT.new(claims).sign('secret') }
358
-
359
- shared_examples_for :json_serialization_parser do
360
- context 'when proper secret given' do
361
- it { JSON::JWT.decode(serialized, 'secret').should == signed }
362
- end
363
-
364
- context 'when verification skipped' do
365
- it { JSON::JWT.decode(serialized, :skip_verification).should == signed }
366
- end
367
-
368
- context 'when wrong secret given' do
369
- it do
370
- expect do
371
- JSON::JWT.decode serialized, 'wrong'
372
- end.to raise_error JSON::JWT::VerificationFailed
373
- end
374
- end
375
- end
376
-
377
- context 'when general' do
378
- let(:serialized) do
379
- {
380
- payload: UrlSafeBase64.encode64(claims.to_json),
381
- signatures: [{
382
- protected: UrlSafeBase64.encode64(signed.header.to_json),
383
- signature: UrlSafeBase64.encode64(signed.signature)
384
- }]
385
- }
386
- end
387
- it_behaves_like :json_serialization_parser
388
- end
389
-
390
- context 'when flattened' do
391
- let(:serialized) do
392
- {
393
- protected: UrlSafeBase64.encode64(signed.header.to_json),
394
- payload: UrlSafeBase64.encode64(claims.to_json),
395
- signature: UrlSafeBase64.encode64(signed.signature)
396
- }
397
- end
398
- it_behaves_like :json_serialization_parser
399
- end
400
- end
401
- end
402
-
403
- context 'when encrypted' do
404
- let(:input) { jwt.encrypt(public_key).to_s }
405
- let(:shared_key) { SecureRandom.hex 16 } # default shared key is too short
406
-
407
- it 'should decryptable' do
408
- JSON::JWT.decode(input, private_key).should be_instance_of JSON::JWE
409
- end
410
-
411
- context 'when :skip_decryption given as secret/key' do
412
- it 'should skip verification' do
413
- expect do
414
- jwe = JSON::JWT.decode input, :skip_decryption
415
- jwe.should be_instance_of JSON::JWE
416
- jwe.header.should == {'alg' => 'RSA1_5', 'enc' => 'A128CBC-HS256'}
417
- end.not_to raise_error
418
- end
419
- end
420
-
421
- context 'when alg & enc is specified' do
422
- context 'when expected' do
423
- it do
424
- expect do
425
- JSON::JWT.decode(input, private_key, 'RSA1_5', 'A128CBC-HS256')
426
- end.not_to raise_error
427
- end
428
- end
429
-
430
- context 'when alg is unexpected' do
431
- it do
432
- expect do
433
- JSON::JWT.decode(input, private_key, 'dir', 'A128CBC-HS256')
434
- end.to raise_error JSON::JWE::UnexpectedAlgorithm, 'Unexpected alg header'
435
- end
436
- end
437
-
438
- context 'when enc is unexpected' do
439
- it do
440
- expect do
441
- JSON::JWT.decode(input, private_key, 'RSA1_5', 'A128GCM')
442
- end.to raise_error JSON::JWE::UnexpectedAlgorithm, 'Unexpected enc header'
443
- end
444
- end
445
- end
446
- end
447
-
448
- context 'when JSON parse failed' do
449
- it do
450
- expect do
451
- JSON::JWT.decode('header.payload.signature')
452
- end.to raise_error JSON::JWT::InvalidFormat
453
- end
454
- end
455
-
456
- context 'when unexpected format' do
457
- context 'when too few dots' do
458
- it do
459
- expect do
460
- JSON::JWT.decode 'header'
461
- end.to raise_error JSON::JWT::InvalidFormat
462
- end
463
- end
464
-
465
- context 'when too many dots' do
466
- it do
467
- expect do
468
- JSON::JWT.decode 'header.payload.signature.something.wrong'
469
- end.to raise_error JSON::JWT::InvalidFormat
470
- end
471
- end
472
- end
473
- end
474
-
475
- describe '.pretty_generate' do
476
- subject { JSON::JWT.pretty_generate jws.to_s }
477
- its(:size) { should == 2 }
478
- its(:first) do
479
- should == <<~HEADER.chop
480
- {
481
- "typ": "JWT",
482
- "alg": "HS256"
483
- }
484
- HEADER
485
- end
486
- its(:last) do
487
- should == <<~HEADER.chop
488
- {
489
- "iss": "joe",
490
- "exp": 1300819380,
491
- "http://example.com/is_root": true
492
- }
493
- HEADER
494
- end
495
- end
496
- end
data/spec/spec_helper.rb DELETED
@@ -1,28 +0,0 @@
1
- require 'simplecov'
2
-
3
- SimpleCov.start do
4
- add_filter 'spec'
5
- end
6
-
7
- require 'rspec'
8
- require 'rspec/its'
9
- require 'json/jwt'
10
-
11
- RSpec.configure do |config|
12
- config.expect_with :rspec do |c|
13
- c.syntax = [:should, :expect]
14
- end
15
- end
16
-
17
- def gcm_supported?
18
- ['aes-128-gcm', 'aes-128-gcm'].all? do |alg|
19
- OpenSSL::Cipher.ciphers.include? alg
20
- end
21
- end
22
-
23
- def pss_supported?
24
- OpenSSL::VERSION >= '2.1.0'
25
- end
26
-
27
- require 'helpers/sign_key_fixture_helper'
28
- require 'helpers/nimbus_spec_helper'