json-jwt 1.9.4 → 1.10.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.

Potentially problematic release.


This version of json-jwt might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f808ae988b45e4c8e03f0afcee499e0d4c89295e
4
- data.tar.gz: f0f2cd732d906a495cc247afc0fd7eaa18725be2
2
+ SHA256:
3
+ metadata.gz: 0f805fa120c4c633a6be48aab961f504aa3e7d5f68aee05f13585e3751201c67
4
+ data.tar.gz: bb26869e462704b7ca5ae9109cd07749b76fc6ee53fc99a6db70238dbfa51c77
5
5
  SHA512:
6
- metadata.gz: 5c6e99521dd9ec520097930ab4a0094f43b3e263f56c701eebc7f1278f75a51b2abf12dee99729efcf51db8d7dd40645e9546e6ad1e2ea8600e8284d00cedbfd
7
- data.tar.gz: 5b87068577c488f213de6a2fe2346d757ee01d1c92aca73e2a87dbd3af07f28b321d511afb4968cd228afb47a41822c3b0040320ef47760629699701a8d8c0cc
6
+ metadata.gz: f2673b42a974d7b9d003f48cf17ef15580d948ef5f06ea8d4c7f46e56249d3849e342720974fcca3a979014cfc898753a541ce851099459f559568f3523f5100
7
+ data.tar.gz: 749aa5e6eadb127674086f77e05e691a162dddfa4cb2d3b4132a1c96649f7a8001b506169dc45112fca117afa67ca16549b090b2ad70fd7275cae2583db735ee
@@ -3,9 +3,9 @@ before_install:
3
3
  - git submodule update --init --recursive
4
4
 
5
5
  rvm:
6
- - 2.3.6
7
- - 2.4.3
8
- - 2.5.0
6
+ - 2.3.7
7
+ - 2.4.4
8
+ - 2.5.1
9
9
 
10
10
  jdk:
11
11
  - oraclejdk8
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.9.4
1
+ 1.10.0
@@ -11,7 +11,8 @@ Gem::Specification.new do |gem|
11
11
  gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
12
12
  gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
13
13
  gem.require_paths = ['lib']
14
- gem.add_runtime_dependency 'activesupport'
14
+ gem.required_ruby_version = '>= 2.3'
15
+ gem.add_runtime_dependency 'activesupport', '>= 4.2'
15
16
  gem.add_runtime_dependency 'bindata'
16
17
  gem.add_runtime_dependency 'aes_key_wrap'
17
18
  gem.add_development_dependency 'rake'
@@ -56,11 +56,11 @@ module JSON
56
56
  end
57
57
  end
58
58
 
59
- def decode(input, key_or_secret = nil, algorithms = nil, encryption_methods = nil)
59
+ def decode(input, key_or_secret = nil, algorithms = nil, encryption_methods = nil, allow_blank_payload = false)
60
60
  if input.is_a? Hash
61
- decode_json_serialized input, key_or_secret, algorithms, encryption_methods
61
+ decode_json_serialized input, key_or_secret, algorithms, encryption_methods, allow_blank_payload
62
62
  else
63
- decode_compact_serialized input, key_or_secret, algorithms, encryption_methods
63
+ decode_compact_serialized input, key_or_secret, algorithms, encryption_methods, allow_blank_payload
64
64
  end
65
65
  rescue JSON::ParserError, ArgumentError
66
66
  raise JWT::InvalidFormat.new("Invalid JSON Format")
@@ -248,7 +248,7 @@ module JSON
248
248
  end
249
249
 
250
250
  class << self
251
- def decode_compact_serialized(input, private_key_or_secret, algorithms = nil, encryption_methods = nil)
251
+ def decode_compact_serialized(input, private_key_or_secret, algorithms = nil, encryption_methods = nil, _allow_blank_payload = false)
252
252
  unless input.count('.') + 1 == NUM_OF_SEGMENTS
253
253
  raise InvalidFormat.new("Invalid JWE Format. JWE should include #{NUM_OF_SEGMENTS} segments.")
254
254
  end
@@ -268,7 +268,7 @@ module JSON
268
268
  jwe
269
269
  end
270
270
 
271
- def decode_json_serialized(input, private_key_or_secret, algorithms = nil, encryption_methods = nil)
271
+ def decode_json_serialized(input, private_key_or_secret, algorithms = nil, encryption_methods = nil, _allow_blank_payload = false)
272
272
  input = input.with_indifferent_access
273
273
  jwe_encrypted_key = if input[:recipients].present?
274
274
  input[:recipients].first[:encrypted_key]
@@ -35,6 +35,7 @@ module JSON
35
35
  if hash_or_jwt.is_a? JSON::JWT
36
36
  self.header.update hash_or_jwt.header
37
37
  self.signature = hash_or_jwt.signature
38
+ self.blank_payload = hash_or_jwt.blank_payload
38
39
  end
39
40
  self
40
41
  end
@@ -118,6 +119,7 @@ module JSON
118
119
  verify_ecdsa_group! private_key
119
120
  asn1_to_raw(
120
121
  private_key.dsa_sign_asn1(digest.digest signature_base_string),
122
+ # private_key.sign(digest, signature_base_string), # NOTE: this causes `undefined method `private?'` error in ruby 2.3
121
123
  private_key
122
124
  )
123
125
  else
@@ -139,10 +141,7 @@ module JSON
139
141
  when ecdsa?
140
142
  public_key = public_key_or_secret
141
143
  verify_ecdsa_group! public_key
142
- public_key.dsa_verify_asn1(
143
- digest.digest(signature_base_string),
144
- raw_to_asn1(signature, public_key)
145
- )
144
+ public_key.verify digest, raw_to_asn1(signature, public_key), signature_base_string
146
145
  else
147
146
  raise UnexpectedAlgorithm.new('Unknown Signature Algorithm')
148
147
  end
@@ -176,15 +175,18 @@ module JSON
176
175
  end
177
176
 
178
177
  class << self
179
- def decode_compact_serialized(input, public_key_or_secret, algorithms = nil)
178
+ def decode_compact_serialized(input, public_key_or_secret, algorithms = nil, allow_blank_payload = false)
180
179
  unless input.count('.') + 1 == NUM_OF_SEGMENTS
181
180
  raise InvalidFormat.new("Invalid JWS Format. JWS should include #{NUM_OF_SEGMENTS} segments.")
182
181
  end
183
182
  header, claims, signature = input.split('.', JWS::NUM_OF_SEGMENTS).collect do |segment|
184
183
  Base64.urlsafe_decode64 segment.to_s
185
184
  end
186
- header, claims = [header, claims].collect do |json|
187
- JSON.parse(json).with_indifferent_access
185
+ header = JSON.parse(header).with_indifferent_access
186
+ if allow_blank_payload && claims == ''
187
+ claims = nil
188
+ else
189
+ claims = JSON.parse(claims).with_indifferent_access
188
190
  end
189
191
  jws = new claims
190
192
  jws.header = header
@@ -194,7 +196,7 @@ module JSON
194
196
  jws
195
197
  end
196
198
 
197
- def decode_json_serialized(input, public_key_or_secret, algorithms = nil)
199
+ def decode_json_serialized(input, public_key_or_secret, algorithms = nil, allow_blank_payload = false)
198
200
  input = input.with_indifferent_access
199
201
  header, payload, signature = if input[:signatures].present?
200
202
  [
@@ -210,7 +212,7 @@ module JSON
210
212
  end
211
213
  end
212
214
  compact_serialized = [header, payload, signature].join('.')
213
- decode_compact_serialized compact_serialized, public_key_or_secret, algorithms
215
+ decode_compact_serialized compact_serialized, public_key_or_secret, algorithms, allow_blank_payload
214
216
  end
215
217
  end
216
218
  end
@@ -6,6 +6,7 @@ require 'json/jose'
6
6
 
7
7
  module JSON
8
8
  class JWT < ActiveSupport::HashWithIndifferentAccess
9
+ attr_accessor :blank_payload
9
10
  attr_accessor :signature
10
11
 
11
12
  class Exception < StandardError; end
@@ -19,8 +20,10 @@ module JSON
19
20
  @content_type = 'application/jwt'
20
21
  self.typ = :JWT
21
22
  self.alg = :none
22
- [:exp, :nbf, :iat].each do |key|
23
- claims[key] = claims[key].to_i if claims[key]
23
+ unless claims.nil?
24
+ [:exp, :nbf, :iat].each do |key|
25
+ claims[key] = claims[key].to_i if claims[key]
26
+ end
24
27
  end
25
28
  update claims
26
29
  end
@@ -71,6 +74,22 @@ module JSON
71
74
  end
72
75
  end
73
76
 
77
+ def to_json *args
78
+ if @blank_payload && args.empty?
79
+ ''
80
+ else
81
+ super
82
+ end
83
+ end
84
+
85
+ def update claims
86
+ if claims.nil?
87
+ @blank_payload = true
88
+ else
89
+ super
90
+ end
91
+ end
92
+
74
93
  def pretty_generate
75
94
  [
76
95
  JSON.pretty_generate(header),
@@ -79,10 +98,10 @@ module JSON
79
98
  end
80
99
 
81
100
  class << self
82
- def decode_compact_serialized(jwt_string, key_or_secret, algorithms = nil, encryption_methods = nil)
101
+ def decode_compact_serialized(jwt_string, key_or_secret, algorithms = nil, encryption_methods = nil, allow_blank_payload = false)
83
102
  case jwt_string.count('.') + 1
84
103
  when JWS::NUM_OF_SEGMENTS
85
- JWS.decode_compact_serialized jwt_string, key_or_secret, algorithms
104
+ JWS.decode_compact_serialized jwt_string, key_or_secret, algorithms, allow_blank_payload
86
105
  when JWE::NUM_OF_SEGMENTS
87
106
  JWE.decode_compact_serialized jwt_string, key_or_secret, algorithms, encryption_methods
88
107
  else
@@ -90,10 +109,10 @@ module JSON
90
109
  end
91
110
  end
92
111
 
93
- def decode_json_serialized(input, key_or_secret, algorithms = nil, encryption_methods = nil)
112
+ def decode_json_serialized(input, key_or_secret, algorithms = nil, encryption_methods = nil, allow_blank_payload = false)
94
113
  input = input.with_indifferent_access
95
114
  if (input[:signatures] || input[:signature]).present?
96
- JWS.decode_json_serialized input, key_or_secret, algorithms
115
+ JWS.decode_json_serialized input, key_or_secret, algorithms, allow_blank_payload
97
116
  elsif input[:ciphertext].present?
98
117
  JWE.decode_json_serialized input, key_or_secret, algorithms, encryption_methods
99
118
  else
@@ -7,9 +7,17 @@ describe JSON::JWS do
7
7
  _jwt_.alg = alg
8
8
  _jwt_
9
9
  end
10
+ let(:jwt_blank) do
11
+ _jwt_ = JSON::JWT.new nil
12
+ _jwt_.alg = alg
13
+ _jwt_
14
+ end
10
15
  let(:jws) { JSON::JWS.new jwt }
16
+ let(:jws_blank) { JSON::JWS.new jwt_blank }
11
17
  let(:signed) { jws.sign! private_key_or_secret }
18
+ let(:signed_blank) { jws_blank.sign! private_key_or_secret }
12
19
  let(:decoded) { JSON::JWT.decode signed.to_s, public_key_or_secret }
20
+ let(:decoded_blank) { JSON::JWT.decode signed_blank.to_s, public_key_or_secret, nil, nil, true }
13
21
  let(:claims) do
14
22
  {
15
23
  iss: 'joe',
@@ -27,6 +35,16 @@ describe JSON::JWS do
27
35
  :RS512 => 'EHeGM2Mo3ghhUfSB99AlREehrbC6OPE-nYL_rwf88ysTnJ8L1QQ0UuCrXq4SpRutGLK_bYTK3ZALvFRPoOgK_g0QWmqv6qjQRU_QTxoq8y8APP-IgKKDuIiGH6daBV2rAPLDReqYNKsKjmTvZJo2c0a0e_WZkkj_ZwpgjTG3v0gW9lbDAzLJDz18eqtR4ZO7JTu_fyNrUrNk-w2_wpxSsn9sygIMp0lKE0_pt0b01fz3gjTDjlltU0cKSalUp4geaBDH7QRcexrolIctdQFbNKTXQxoigxD3NLNkKGH7f6A8KZdcOm8AnEjullcZs8_OWGnW43p1qrxoBRSivb9pqQ'
28
36
  }
29
37
  end
38
+ let(:expected_signature_blank_payload) do
39
+ {
40
+ :HS256 => 'iRFMM3GknVfzRTxlVQT87jfIw32Ik3lUYNGePPk5wnM',
41
+ :HS384 => 'rxyzr3I2RWRBgQaewQt3yjdp3BqkrFh-iHcet318OYHWhXvyzAE0npf0l0xi5DOV',
42
+ :HS512 => 'VDHOrPYrwycjaKbwccObXi6dmw4fVFqiFsNFQjqYHQAkxJGxqhfVLc1_WfKMa6C7vGSGroabaVdK7nn08XPdSQ',
43
+ :RS256 => 'WthQjouPVbErM7McwSY4slJjHaWqmFg1qKdmTDvttkiyAEcTjVViJkNHH9Mp573h13cXtLob1xh3UJYh5_-hSA4Y24zdyck3jp3fsOusflp1cMmhWXZ2nETKeWCEJDKRAnWynHqkwes7tgWmS0gVeuljeNkuovJlHmNRcoMR9Z3ZuiHfc2WFh-iFbM5Zne1y-_SSgAZwOD20P0Ysn28DtJTlXcm74ENqhLEJnvHS-872d6surb23kHMns43GtT5bm-aJoMLct0nO1GBapQAiKUknTsw24IfOkX4vJNQzIWVSzx3zOxXjcVHlH92af6NknIlPCfRparLC9YEK2NkJYg',
44
+ :RS384 => 'Jy6XNLNAyujRHYoCOtFqu7z0imHZMiwkwBr73ok_DDSDxQSA9ryt_q_tX0u8knpAIRcTJuNA0-s5DkGbpIj9coKgZ5JBvE_n9ijvNubImf8_vCDDitJemzUtnJypb9GbP4A3nWDAZC0KONVqlxpy92-9xrG5sFEzaYCFYZYnXv8kmmQEIVI1GXw4_Fx8HxRu5cae9WWTgaKQOFG54S303C0H966C1o6d9o3HQH7x8GEl632qBw4LzONWr_QpCN-UFgmJHO7yBwaP-RWnLDW3hYlb4IybRIvMQQicjkjNaNwLTmwo31orVxO53GcSjyhU2y_R843nQcNjTT_lD1QRvg',
45
+ :RS512 => 'ws2HZ6wvh8GMrFKiIHXDogyx8HFpa4wvrLxfZaMfCoMPf0SZ4V3tiEZRWfrxyvwpsdBj2Mgm5lt3IYAHhlI2hqWvuikDq6tuViloaAIm2xwTU060bF0GL1tQJ-h20wUukJ6fsWet8M9DNg7hcElYQMawHhk4L91YUtY2hKT_uWgPih_pn0Hq5Ve0at4CwAyXXTwCYSEH23PMsUdDfE5tfCyvL2bNQ71Ld_MvQS1NLS7hydzEtfxLK-UkDQVclFmEM3JXrPG7YSRodtKlwJ-ESDx6CaJXXDAgitSF32dslcIkmOXRJqjNmF15i_aVg0ExiU92WTpCrdwzWTt4Aphqlw',
46
+ }
47
+ end
30
48
 
31
49
  shared_examples_for :jwt_with_alg do
32
50
  it { should == jwt }
@@ -45,11 +63,37 @@ describe JSON::JWS do
45
63
  end
46
64
  end
47
65
 
66
+ describe 'decode' do
67
+ let(:alg) { :RS256 }
68
+ let(:private_key_or_secret) { private_key }
69
+ let(:public_key_or_secret) { public_key }
70
+
71
+ describe 'blank payload not allowed' do
72
+ it 'should raise format error' do
73
+ expect do
74
+ JSON::JWT.decode signed_blank.to_s, public_key_or_secret
75
+ end.to raise_error JSON::JWT::InvalidFormat
76
+ end
77
+ end
78
+ describe 'blank payload allowed' do
79
+ it 'should not raise an error' do
80
+ expect do
81
+ JSON::JWT.decode signed_blank.to_s, public_key_or_secret, nil, nil, true
82
+ end.to_not raise_error
83
+ end
84
+ end
85
+ end
86
+
48
87
  describe '#sign!' do
49
88
  shared_examples_for :generate_expected_signature do
50
89
  it do
51
90
  Base64.urlsafe_encode64(signed.signature, padding: false).should == expected_signature[alg]
52
91
  end
92
+ context 'with blank payload' do
93
+ it do
94
+ Base64.urlsafe_encode64(signed_blank.signature, padding: false).should == expected_signature_blank_payload[alg]
95
+ end
96
+ end
53
97
  end
54
98
  subject { signed }
55
99
 
@@ -176,6 +220,32 @@ describe JSON::JWS do
176
220
  decoded[:'http://example.com/is_root'] == true
177
221
  end
178
222
  end
223
+
224
+ context 'with blank payload' do
225
+ it do
226
+ expect { decoded_blank }.not_to raise_error
227
+ decoded_blank.should be_a JSON::JWT
228
+ end
229
+
230
+ describe 'header' do
231
+ let(:header) { decoded_blank.header }
232
+ it 'should be parsed successfully' do
233
+ header[:typ].should == 'JWT'
234
+ header[:alg].should == alg.to_s
235
+ end
236
+ end
237
+
238
+ describe 'claims' do
239
+ it 'should be parsed successfully' do
240
+ p decoded_blank.blank_payload
241
+ decoded_blank.blank_payload.should == true
242
+ decoded_blank[:iss].should == nil
243
+ decoded_blank[:exp].should == nil
244
+ decoded[:'http://example.com/is_root'] == nil
245
+ end
246
+ end
247
+ end
248
+
179
249
  end
180
250
  subject { decoded }
181
251
 
@@ -274,6 +344,12 @@ describe JSON::JWS do
274
344
  jws.to_json.should == claims.to_json
275
345
  end
276
346
  end
347
+ context 'with blank payload' do
348
+ it 'should JSONize payload' do
349
+ puts ("jws_blank: #{jws_blank.to_json.inspect}")
350
+ jws_blank.to_json.should == ''
351
+ end
352
+ end
277
353
 
278
354
  context 'when syntax option given' do
279
355
  context 'when general' do
@@ -286,6 +362,17 @@ describe JSON::JWS do
286
362
  }]
287
363
  }.to_json
288
364
  end
365
+ context 'with blank payload' do
366
+ it 'should return General JWS JSON Serialization' do
367
+ signed_blank.to_json(syntax: :general).should == {
368
+ payload: '',
369
+ signatures: [{
370
+ protected: Base64.urlsafe_encode64(signed_blank.header.to_json, padding: false),
371
+ signature: Base64.urlsafe_encode64(signed_blank.signature, padding: false)
372
+ }]
373
+ }.to_json
374
+ end
375
+ end
289
376
 
290
377
  context 'when not signed yet' do
291
378
  it 'should not fail' do
@@ -297,6 +384,17 @@ describe JSON::JWS do
297
384
  }]
298
385
  }.to_json
299
386
  end
387
+ context 'with blank payload' do
388
+ it 'should not fail' do
389
+ jws_blank.to_json(syntax: :general).should == {
390
+ payload: '',
391
+ signatures: [{
392
+ protected: Base64.urlsafe_encode64(jws_blank.header.to_json, padding: false),
393
+ signature: Base64.urlsafe_encode64('', padding: false)
394
+ }]
395
+ }.to_json
396
+ end
397
+ end
300
398
  end
301
399
  end
302
400
 
@@ -308,6 +406,15 @@ describe JSON::JWS do
308
406
  signature: Base64.urlsafe_encode64(signed.signature, padding: false)
309
407
  }.to_json
310
408
  end
409
+ context 'with blank payload' do
410
+ it 'should return Flattened JWS JSON Serialization' do
411
+ signed_blank.to_json(syntax: :flattened).should == {
412
+ protected: Base64.urlsafe_encode64(signed_blank.header.to_json, padding: false),
413
+ payload: '',
414
+ signature: Base64.urlsafe_encode64(signed_blank.signature, padding: false)
415
+ }.to_json
416
+ end
417
+ end
311
418
 
312
419
  context 'when not signed yet' do
313
420
  it 'should not fail' do
@@ -317,6 +424,15 @@ describe JSON::JWS do
317
424
  signature: Base64.urlsafe_encode64('', padding: false)
318
425
  }.to_json
319
426
  end
427
+ context 'with blank payload' do
428
+ it 'should not fail' do
429
+ jws_blank.to_json(syntax: :flattened).should == {
430
+ protected: Base64.urlsafe_encode64(jws_blank.header.to_json, padding: false),
431
+ payload: '',
432
+ signature: Base64.urlsafe_encode64('', padding: false)
433
+ }.to_json
434
+ end
435
+ end
320
436
  end
321
437
  end
322
438
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json-jwt
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.4
4
+ version: 1.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - nov matake
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-01 00:00:00.000000000 Z
11
+ date: 2018-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '4.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '4.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bindata
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -166,7 +166,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
166
166
  requirements:
167
167
  - - ">="
168
168
  - !ruby/object:Gem::Version
169
- version: '0'
169
+ version: '2.3'
170
170
  required_rubygems_version: !ruby/object:Gem::Requirement
171
171
  requirements:
172
172
  - - ">="
@@ -174,7 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
174
174
  version: '0'
175
175
  requirements: []
176
176
  rubyforge_project:
177
- rubygems_version: 2.6.11
177
+ rubygems_version: 2.7.6
178
178
  signing_key:
179
179
  specification_version: 4
180
180
  summary: JSON Web Token and its family (JSON Web Signature, JSON Web Encryption and