json-jwt 1.10.0 → 1.10.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.
Potentially problematic release.
This version of json-jwt might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/json-jwt.gemspec +3 -2
- data/lib/json/jose.rb +1 -1
- data/lib/json/jwe.rb +7 -7
- data/lib/json/jwk.rb +4 -4
- data/lib/json/jws.rb +6 -6
- metadata +3 -45
- data/spec/fixtures/ecdsa/256/private_key.pem +0 -5
- data/spec/fixtures/ecdsa/256/public_key.pem +0 -4
- data/spec/fixtures/ecdsa/384/private_key.pem +0 -6
- data/spec/fixtures/ecdsa/384/public_key.pem +0 -5
- data/spec/fixtures/ecdsa/512/private_key.pem +0 -7
- data/spec/fixtures/ecdsa/512/public_key.pem +0 -6
- data/spec/fixtures/rsa/private_key.der +0 -0
- data/spec/fixtures/rsa/private_key.pem +0 -30
- data/spec/fixtures/rsa/public_key.pem +0 -8
- data/spec/helpers/nimbus_spec_helper.rb +0 -22
- data/spec/helpers/sign_key_fixture_helper.rb +0 -52
- data/spec/interop/with_jsrsasign_spec.rb +0 -49
- data/spec/interop/with_nimbus_jose_spec.rb +0 -99
- data/spec/interop/with_rfc_example_spec.rb +0 -19
- data/spec/json/jwe_spec.rb +0 -351
- data/spec/json/jwk/jwkizable_spec.rb +0 -49
- data/spec/json/jwk/set_spec.rb +0 -75
- data/spec/json/jwk_spec.rb +0 -194
- data/spec/json/jws_spec.rb +0 -440
- data/spec/json/jwt_spec.rb +0 -523
- data/spec/spec_helper.rb +0 -28
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe JSON::JWK::JWKizable do
|
4
|
-
describe '#to_jwk' do
|
5
|
-
subject { key.to_jwk }
|
6
|
-
|
7
|
-
shared_examples_for :jwkizable_as_public do
|
8
|
-
it { should be_instance_of JSON::JWK }
|
9
|
-
it { should include *public_key_attributes.collect(&:to_s) }
|
10
|
-
it { should_not include *private_key_attributes.collect(&:to_s) }
|
11
|
-
end
|
12
|
-
|
13
|
-
shared_examples_for :jwkizable_as_private do
|
14
|
-
it { should be_instance_of JSON::JWK }
|
15
|
-
it { should include *public_key_attributes.collect(&:to_s) }
|
16
|
-
it { should include *private_key_attributes.collect(&:to_s) }
|
17
|
-
end
|
18
|
-
|
19
|
-
describe OpenSSL::PKey::RSA do
|
20
|
-
let(:public_key_attributes) { [:kty, :n, :e] }
|
21
|
-
let(:private_key_attributes) { [:d, :p, :q] }
|
22
|
-
|
23
|
-
describe :public_key do
|
24
|
-
let(:key) { public_key :rsa }
|
25
|
-
it_behaves_like :jwkizable_as_public
|
26
|
-
end
|
27
|
-
|
28
|
-
describe :private_key do
|
29
|
-
let(:key) { private_key :rsa }
|
30
|
-
it_behaves_like :jwkizable_as_private
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
describe OpenSSL::PKey::EC do
|
35
|
-
let(:public_key_attributes) { [:kty, :crv, :x, :y] }
|
36
|
-
let(:private_key_attributes) { [:d] }
|
37
|
-
|
38
|
-
describe :public_key do
|
39
|
-
let(:key) { public_key :ecdsa }
|
40
|
-
it_behaves_like :jwkizable_as_public
|
41
|
-
end
|
42
|
-
|
43
|
-
describe :private_key do
|
44
|
-
let(:key) { private_key :ecdsa }
|
45
|
-
it_behaves_like :jwkizable_as_private
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
data/spec/json/jwk/set_spec.rb
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe JSON::JWK::Set do
|
4
|
-
let(:jwk) { public_key.to_jwk }
|
5
|
-
let(:set) { JSON::JWK::Set.new jwk }
|
6
|
-
|
7
|
-
describe '#content_type' do
|
8
|
-
it do
|
9
|
-
set.content_type.should == 'application/jwk-set+json'
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
context 'when single JWK given' do
|
14
|
-
subject { JSON::JWK::Set.new jwk }
|
15
|
-
it { should == [jwk] }
|
16
|
-
end
|
17
|
-
|
18
|
-
context 'when multiple JWKs given' do
|
19
|
-
subject { JSON::JWK::Set.new jwk, jwk }
|
20
|
-
it { should == [jwk, jwk] }
|
21
|
-
end
|
22
|
-
|
23
|
-
context 'when an Array of JWKs given' do
|
24
|
-
subject { JSON::JWK::Set.new [jwk, jwk] }
|
25
|
-
it { should == [jwk, jwk] }
|
26
|
-
end
|
27
|
-
|
28
|
-
context 'when JSON::JWK given' do
|
29
|
-
subject { JSON::JWK::Set.new jwk }
|
30
|
-
|
31
|
-
it 'should keep JSON::JWK' do
|
32
|
-
subject.each do |jwk|
|
33
|
-
jwk.should be_instance_of JSON::JWK
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
context 'when pure Hash given' do
|
39
|
-
subject { JSON::JWK::Set.new jwk.as_json }
|
40
|
-
|
41
|
-
it 'should convert into JSON::JWK' do
|
42
|
-
subject.each do |jwk|
|
43
|
-
jwk.should be_instance_of JSON::JWK
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
context 'when pure Hash with :keys key given' do
|
49
|
-
subject do
|
50
|
-
JSON::JWK::Set.new(
|
51
|
-
keys: jwk.as_json
|
52
|
-
)
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'should convert into JSON::JWK' do
|
56
|
-
subject.each do |jwk|
|
57
|
-
jwk.should be_instance_of JSON::JWK
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
describe '#as_json' do
|
63
|
-
it 'should become proper JWK set format' do
|
64
|
-
json = set.as_json
|
65
|
-
json.should include :keys
|
66
|
-
json[:keys].should == [jwk]
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe '#to_json' do
|
71
|
-
it do
|
72
|
-
expect { set.to_json }.not_to raise_error
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
data/spec/json/jwk_spec.rb
DELETED
@@ -1,194 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe JSON::JWK do
|
4
|
-
describe '#initialize' do
|
5
|
-
let(:jwk) { JSON::JWK.new key }
|
6
|
-
subject { jwk }
|
7
|
-
|
8
|
-
shared_examples_for :jwk_with_kid do
|
9
|
-
it { should be_instance_of JSON::JWK }
|
10
|
-
describe 'kid' do
|
11
|
-
subject { jwk[:kid] }
|
12
|
-
it { should == jwk.thumbprint }
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
shared_examples_for :jwk_without_kid do
|
17
|
-
it { should be_instance_of JSON::JWK }
|
18
|
-
describe 'kid' do
|
19
|
-
subject { jwk[:kid] }
|
20
|
-
it { should be_blank }
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'when no imput' do
|
25
|
-
it do
|
26
|
-
JSON::JWK.new.should be_blank
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
context 'with OpenSSL::PKey::RSA' do
|
31
|
-
let(:key) { public_key }
|
32
|
-
it_behaves_like :jwk_with_kid
|
33
|
-
end
|
34
|
-
|
35
|
-
context 'with OpenSSL::PKey::EC' do
|
36
|
-
let(:key) { public_key :ecdsa }
|
37
|
-
it_behaves_like :jwk_with_kid
|
38
|
-
end
|
39
|
-
|
40
|
-
context 'with String' do
|
41
|
-
let(:key) { 'secret' }
|
42
|
-
it_behaves_like :jwk_with_kid
|
43
|
-
end
|
44
|
-
|
45
|
-
context 'with JSON::JWK' do
|
46
|
-
let(:key) do
|
47
|
-
JSON::JWK.new(
|
48
|
-
k: 'secret',
|
49
|
-
kty: :oct
|
50
|
-
)
|
51
|
-
end
|
52
|
-
it_behaves_like :jwk_with_kid
|
53
|
-
end
|
54
|
-
|
55
|
-
context 'with Hash' do
|
56
|
-
let(:key) do
|
57
|
-
{
|
58
|
-
k: 'secret',
|
59
|
-
kty: :oct
|
60
|
-
}
|
61
|
-
end
|
62
|
-
it_behaves_like :jwk_with_kid
|
63
|
-
end
|
64
|
-
|
65
|
-
context 'with nothing' do
|
66
|
-
let(:jwk) { JSON::JWK.new }
|
67
|
-
it_behaves_like :jwk_without_kid
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
describe '#content_type' do
|
72
|
-
let(:jwk) { JSON::JWK.new public_key }
|
73
|
-
it do
|
74
|
-
jwk.content_type.should == 'application/jwk+json'
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
context 'when RSA public key given' do
|
79
|
-
let(:jwk) { JSON::JWK.new public_key }
|
80
|
-
it { jwk.keys.collect(&:to_sym).should include :kty, :e, :n }
|
81
|
-
its(:kty) { jwk[:kty].should == :RSA }
|
82
|
-
its(:e) { jwk[:e].should == Base64.urlsafe_encode64(public_key.e.to_s(2), padding: false) }
|
83
|
-
its(:n) { jwk[:n].should == Base64.urlsafe_encode64(public_key.n.to_s(2), padding: false) }
|
84
|
-
|
85
|
-
context 'when kid/use options given' do
|
86
|
-
let(:jwk) { JSON::JWK.new public_key, kid: '12345', use: :sig }
|
87
|
-
it { jwk.keys.collect(&:to_sym).should include :kid, :use }
|
88
|
-
its(:kid) { jwk[:kid].should == '12345' }
|
89
|
-
its(:use) { jwk[:use].should == :sig }
|
90
|
-
end
|
91
|
-
|
92
|
-
describe '#thumbprint' do
|
93
|
-
context 'using default hash function' do
|
94
|
-
subject { jwk.thumbprint }
|
95
|
-
it { should == 'nuBTimkcSt_AuEsD8Yv3l8CoGV31bu_3gsRDGN1iVKA' }
|
96
|
-
end
|
97
|
-
|
98
|
-
context 'using SHA512 hash function' do
|
99
|
-
subject { jwk.thumbprint :SHA512 }
|
100
|
-
it { should == '6v7pXTnQLMiQgvJlPJUdhAUSuGLzgF8C1r3ABAMFet6bc53ea-Pq4ZGbGu3RoAFsNRT1-RhTzDqtqXuLU6NOtw' }
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
describe '#to_key' do
|
105
|
-
it { jwk.to_key.should be_instance_of OpenSSL::PKey::RSA }
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
context 'when EC public key given' do
|
110
|
-
let(:jwk) { JSON::JWK.new public_key(:ecdsa) }
|
111
|
-
let(:expected_coordinates) do
|
112
|
-
{
|
113
|
-
256 => {
|
114
|
-
x: 'saPyrO4Lh9kh2FxrF9y1QVmZznWnRRJwpr12UHqzrVY',
|
115
|
-
y: 'MMz4W9zzqlrJhqr-JyrpvlnaIIyZQE6DfrgPkxMAw1M'
|
116
|
-
},
|
117
|
-
384 => {
|
118
|
-
x: 'plzApyFnK7qzhg5XnIZbFj2hZoH2Vdl4-RFm7DnsNMG9tyqrpfq2RyjfKABbcFRt',
|
119
|
-
y: 'ixBzffhk3fcbmeipGLkvQBNCzeNm6QL3hOUTH6IFBzOL0Y7HsGTopNTTspLjlivb'
|
120
|
-
},
|
121
|
-
512 => {
|
122
|
-
x: 'AcMCD-a0a6rnE9TvC0mOqF_DGXRg5Y3iTb4eHNwTm2kD6iujx9M_f8d_FGHr0OhpqzEn4rYPYZouGsbIPEgL0q__',
|
123
|
-
y: 'AULYEd8l-bV_BI289aezhSLZ1RDF2ltgDPEy9Y7YtqYa4cJcpiyzVDMpXWwBp6cjg6TXINkoVrVXZhN404ihu4I2'
|
124
|
-
}
|
125
|
-
}
|
126
|
-
end
|
127
|
-
|
128
|
-
[256, 384, 512].each do |digest_length|
|
129
|
-
describe "EC#{digest_length}" do
|
130
|
-
let(:jwk) { JSON::JWK.new public_key(:ecdsa, digest_length: digest_length) }
|
131
|
-
it { jwk.keys.collect(&:to_sym).should include :kty, :crv, :x, :y }
|
132
|
-
its(:kty) { jwk[:kty].should == :EC }
|
133
|
-
its(:x) { jwk[:x].should == expected_coordinates[digest_length][:x] }
|
134
|
-
its(:y) { jwk[:y].should == expected_coordinates[digest_length][:y] }
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
describe 'unknown curve' do
|
139
|
-
it do
|
140
|
-
key = OpenSSL::PKey::EC.new('secp112r2').generate_key
|
141
|
-
expect do
|
142
|
-
JSON::JWK.new key
|
143
|
-
end.to raise_error JSON::JWK::UnknownAlgorithm, 'Unknown EC Curve'
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
describe '#thumbprint' do
|
148
|
-
context 'using default hash function' do
|
149
|
-
subject { jwk.thumbprint }
|
150
|
-
it { should == '-egRpLjyZCqxBh4OOfd8JSvXwayHmNFAUNkbi8exfhc' }
|
151
|
-
end
|
152
|
-
|
153
|
-
context 'using SHA512 hash function' do
|
154
|
-
subject { jwk.thumbprint :SHA512 }
|
155
|
-
it { should == 'B_yXDZJ9doudaVCj5q5vqxshvVtW2IFnz_ypvRt5O60gemkDAhO78L6YMyTWH0ZRm15cO2_laTSaNO9yZQFsvQ' }
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
describe '#to_key' do
|
160
|
-
it { jwk.to_key.should be_instance_of OpenSSL::PKey::EC }
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
context 'when shared secret given' do
|
165
|
-
let(:jwk) { JSON::JWK.new 'secret' }
|
166
|
-
its(:kty) { jwk[:kty].should == :oct }
|
167
|
-
its(:x) { jwk[:k].should == 'secret' }
|
168
|
-
|
169
|
-
describe '#thumbprint' do
|
170
|
-
context 'using default hash function' do
|
171
|
-
subject { jwk.thumbprint }
|
172
|
-
it { should == 'XZPWsTEZFIerowAF9GHzBtq5CkAOcVvIBnkMu0IIQH0' }
|
173
|
-
end
|
174
|
-
|
175
|
-
context 'using SHA512 hash function' do
|
176
|
-
subject { jwk.thumbprint :SHA512 }
|
177
|
-
it { should == 'rK7EtcEe9Xr0kryR9lNnyOTRe7Vb_BglbTBtbcVG2LzvL26_PFaMCwOtiUiXWfCK-wV8vcxjmvbcvV4ZxDE0FQ' }
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
describe '#to_key' do
|
182
|
-
it { jwk.to_key.should be_instance_of String }
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
describe 'unknown key type' do
|
187
|
-
it do
|
188
|
-
key = OpenSSL::PKey::DSA.generate 256
|
189
|
-
expect do
|
190
|
-
JSON::JWK.new key
|
191
|
-
end.to raise_error JSON::JWK::UnknownAlgorithm, 'Unknown Key Type'
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
data/spec/json/jws_spec.rb
DELETED
@@ -1,440 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe JSON::JWS do
|
4
|
-
let(:alg) { :none }
|
5
|
-
let(:jwt) do
|
6
|
-
_jwt_ = JSON::JWT.new claims
|
7
|
-
_jwt_.alg = alg
|
8
|
-
_jwt_
|
9
|
-
end
|
10
|
-
let(:jwt_blank) do
|
11
|
-
_jwt_ = JSON::JWT.new nil
|
12
|
-
_jwt_.alg = alg
|
13
|
-
_jwt_
|
14
|
-
end
|
15
|
-
let(:jws) { JSON::JWS.new jwt }
|
16
|
-
let(:jws_blank) { JSON::JWS.new jwt_blank }
|
17
|
-
let(:signed) { jws.sign! private_key_or_secret }
|
18
|
-
let(:signed_blank) { jws_blank.sign! private_key_or_secret }
|
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 }
|
21
|
-
let(:claims) do
|
22
|
-
{
|
23
|
-
iss: 'joe',
|
24
|
-
exp: 1300819380,
|
25
|
-
:'http://example.com/is_root' => true
|
26
|
-
}
|
27
|
-
end
|
28
|
-
let(:expected_signature) do
|
29
|
-
{
|
30
|
-
:HS256 => 'DyuTgO2Ggb5nrhkkhI-RjVYIBe3o8oL4ijkAn94YPxQ',
|
31
|
-
:HS384 => 'a5-7rr61TG8Snv9xxJ7l064ky-SCq1Mswe9t8HEorvoc_nnfIeUy9WQCLMIli34R',
|
32
|
-
:HS512 => 'ce-GlHDaNwaHfmAFRGp3QPPKvrpruTug2hC1bf6yNlbuvkMwJw2jFZgq_4wmIPetRdiBy7XFq7rrtmw1Im7tmQ',
|
33
|
-
:RS256 => 'E5VELqAdla2Bx1axc9KFxO0EiCr0Mw6HPYX070qGQ8zA_XmyxGPUZLyyWU_6Cn399W-oYBWO2ynLlr8pqqjP3jXevyCeYeGRVN0HzLYiBebEugNnc3hevr7WV2UzfksWRA-Ux2bDv2sz9p_LGbL33wWNxGDvIlpDyZUul_a48nCipS0riBjkTLTSE8dfBxQTXEF5GEUUu99ot6aBLzUhc25nHXSXogXF6MHK-hAcE7f4v-vJ0lbPbHLVGUopIoxoqe4XjoBpzE5UvhrVl5LYbdjbyJhu5ZIA8GLsgwtUFh3dfdIechORoR3k5NSFSv8157bAEa8t4iwgWD2MSNSQnw',
|
34
|
-
:RS384 => 'lT5JbytGKgG9QrwkJuxgw7UjmN9tjkEQW9pVGR2XnKEdC0_wLNIzAmT-jTwyMDGBLUkWO7opDOP6Xy6_DOTg58k9PwVkyQzrLnmxJMEng2Q-aMqcitRSIvUk3DPy8kemp8yUPls9NzWmByM2GoUVHbDsR0r-tZN-g_9QYev32mvMhjMr30JI5S2xiRjc9m2GAaXMOQmNTovJgV4bgCp4UjruCrA0BD1JJwDqKYoR_YYr_ALcVjD_LUgy80udJvbi8MAYJVUf0QYtQDrX2wnT_-eiiWjD5XafLuXEQVDRh-v2MKAwdvtXMq5cZ08Zjl2SyHxJ3OqhEeWPvYGltxZh_A',
|
35
|
-
:RS512 => 'EHeGM2Mo3ghhUfSB99AlREehrbC6OPE-nYL_rwf88ysTnJ8L1QQ0UuCrXq4SpRutGLK_bYTK3ZALvFRPoOgK_g0QWmqv6qjQRU_QTxoq8y8APP-IgKKDuIiGH6daBV2rAPLDReqYNKsKjmTvZJo2c0a0e_WZkkj_ZwpgjTG3v0gW9lbDAzLJDz18eqtR4ZO7JTu_fyNrUrNk-w2_wpxSsn9sygIMp0lKE0_pt0b01fz3gjTDjlltU0cKSalUp4geaBDH7QRcexrolIctdQFbNKTXQxoigxD3NLNkKGH7f6A8KZdcOm8AnEjullcZs8_OWGnW43p1qrxoBRSivb9pqQ'
|
36
|
-
}
|
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
|
48
|
-
|
49
|
-
shared_examples_for :jwt_with_alg do
|
50
|
-
it { should == jwt }
|
51
|
-
its(:header) { should == jwt.header }
|
52
|
-
end
|
53
|
-
|
54
|
-
context 'before sign' do
|
55
|
-
subject { jws }
|
56
|
-
it_behaves_like :jwt_with_alg
|
57
|
-
its(:signature) { should be_nil }
|
58
|
-
end
|
59
|
-
|
60
|
-
describe '#content_type' do
|
61
|
-
it do
|
62
|
-
jws.content_type.should == 'application/jose'
|
63
|
-
end
|
64
|
-
end
|
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
|
-
|
87
|
-
describe '#sign!' do
|
88
|
-
shared_examples_for :generate_expected_signature do
|
89
|
-
it do
|
90
|
-
Base64.urlsafe_encode64(signed.signature, padding: false).should == expected_signature[alg]
|
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
|
97
|
-
end
|
98
|
-
subject { signed }
|
99
|
-
|
100
|
-
[:HS256, :HS384, :HS512].each do |algorithm|
|
101
|
-
describe algorithm do
|
102
|
-
let(:alg) { algorithm }
|
103
|
-
|
104
|
-
context 'when String key given' do
|
105
|
-
let(:private_key_or_secret) { shared_secret }
|
106
|
-
it_behaves_like :jwt_with_alg
|
107
|
-
it_behaves_like :generate_expected_signature
|
108
|
-
end
|
109
|
-
|
110
|
-
context 'when JSON::JWK key given' do
|
111
|
-
let(:private_key_or_secret) { JSON::JWK.new shared_secret }
|
112
|
-
it_behaves_like :jwt_with_alg
|
113
|
-
it_behaves_like :generate_expected_signature
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
[:RS256, :RS384, :RS512].each do |algorithm|
|
119
|
-
describe algorithm do
|
120
|
-
let(:alg) { algorithm }
|
121
|
-
|
122
|
-
context 'when OpenSSL::PKey::RSA key given' do
|
123
|
-
let(:private_key_or_secret) { private_key }
|
124
|
-
it_behaves_like :jwt_with_alg
|
125
|
-
it_behaves_like :generate_expected_signature
|
126
|
-
end
|
127
|
-
|
128
|
-
context 'when JSON::JWK key given' do
|
129
|
-
let(:private_key_or_secret) { JSON::JWK.new private_key }
|
130
|
-
it_behaves_like :jwt_with_alg
|
131
|
-
it_behaves_like :generate_expected_signature
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
[:ES256, :ES384, :ES512].each do |algorithm|
|
137
|
-
describe algorithm do
|
138
|
-
let(:alg) { algorithm }
|
139
|
-
|
140
|
-
shared_examples_for :self_verifiable do
|
141
|
-
it 'should be self-verifiable' do
|
142
|
-
expect do
|
143
|
-
JSON::JWT.decode(
|
144
|
-
JSON::JWT.new(claims).sign(
|
145
|
-
private_key_or_secret, algorithm
|
146
|
-
).to_s, public_key_or_secret
|
147
|
-
)
|
148
|
-
end.not_to raise_error
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
context 'when OpenSSL::PKey::EC key given' do
|
153
|
-
let(:private_key_or_secret) { private_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i }
|
154
|
-
let(:public_key_or_secret) { public_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i }
|
155
|
-
it_behaves_like :jwt_with_alg
|
156
|
-
it_behaves_like :self_verifiable
|
157
|
-
end
|
158
|
-
|
159
|
-
context 'when JSON::JWK key given' do
|
160
|
-
let(:private_key_or_secret) { JSON::JWK.new(private_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i) }
|
161
|
-
let(:public_key_or_secret) { JSON::JWK.new(public_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i) }
|
162
|
-
it_behaves_like :jwt_with_alg
|
163
|
-
it_behaves_like :self_verifiable
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
context 'when JSON::JWK::Set key given' do
|
169
|
-
let(:alg) { :HS256 }
|
170
|
-
let(:kid) { 'kid' }
|
171
|
-
let(:jwks) do
|
172
|
-
jwk = JSON::JWK.new shared_secret, kid: kid
|
173
|
-
JSON::JWK::Set.new jwk, JSON::JWK.new('another')
|
174
|
-
end
|
175
|
-
let(:signed) { jws.sign!(jwks) }
|
176
|
-
|
177
|
-
context 'when jwk is found by given kid' do
|
178
|
-
before { jws.kid = kid }
|
179
|
-
it { should == jws.sign!('secret') }
|
180
|
-
end
|
181
|
-
|
182
|
-
context 'otherwise' do
|
183
|
-
it do
|
184
|
-
expect do
|
185
|
-
subject
|
186
|
-
end.to raise_error JSON::JWK::Set::KidNotFound
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
describe 'unknown algorithm' do
|
192
|
-
let(:alg) { :unknown }
|
193
|
-
it do
|
194
|
-
expect do
|
195
|
-
jws.sign! 'key'
|
196
|
-
end.to raise_error JSON::JWS::UnexpectedAlgorithm
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
describe '#verify!' do
|
202
|
-
shared_examples_for :success_signature_verification do
|
203
|
-
it do
|
204
|
-
expect { decoded }.not_to raise_error
|
205
|
-
decoded.should be_a JSON::JWT
|
206
|
-
end
|
207
|
-
|
208
|
-
describe 'header' do
|
209
|
-
let(:header) { decoded.header }
|
210
|
-
it 'should be parsed successfully' do
|
211
|
-
header[:typ].should == 'JWT'
|
212
|
-
header[:alg].should == alg.to_s
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
describe 'claims' do
|
217
|
-
it 'should be parsed successfully' do
|
218
|
-
decoded[:iss].should == 'joe'
|
219
|
-
decoded[:exp].should == 1300819380
|
220
|
-
decoded[:'http://example.com/is_root'] == true
|
221
|
-
end
|
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
|
-
|
249
|
-
end
|
250
|
-
subject { decoded }
|
251
|
-
|
252
|
-
[:HS256, :HS384, :HS512].each do |algorithm|
|
253
|
-
describe algorithm do
|
254
|
-
let(:alg) { algorithm }
|
255
|
-
let(:private_key_or_secret) { shared_secret }
|
256
|
-
|
257
|
-
context 'when String key given' do
|
258
|
-
let(:public_key_or_secret) { shared_secret }
|
259
|
-
it_behaves_like :success_signature_verification
|
260
|
-
end
|
261
|
-
|
262
|
-
context 'when JSON::JWK key given' do
|
263
|
-
let(:public_key_or_secret) { JSON::JWK.new shared_secret }
|
264
|
-
it_behaves_like :success_signature_verification
|
265
|
-
end
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
|
-
[:RS256, :RS384, :RS512].each do |algorithm|
|
270
|
-
describe algorithm do
|
271
|
-
let(:alg) { algorithm }
|
272
|
-
let(:private_key_or_secret) { private_key }
|
273
|
-
|
274
|
-
context 'when OpenSSL::PKey::RSA key given' do
|
275
|
-
let(:public_key_or_secret) { public_key }
|
276
|
-
it_behaves_like :success_signature_verification
|
277
|
-
end
|
278
|
-
|
279
|
-
context 'when JSON::JWK key given' do
|
280
|
-
let(:public_key_or_secret) { JSON::JWK.new public_key }
|
281
|
-
it_behaves_like :success_signature_verification
|
282
|
-
end
|
283
|
-
end
|
284
|
-
end
|
285
|
-
|
286
|
-
[:ES256, :ES384, :ES512].each do |algorithm|
|
287
|
-
describe algorithm do
|
288
|
-
let(:alg) { algorithm }
|
289
|
-
let(:private_key_or_secret) { private_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i }
|
290
|
-
|
291
|
-
context 'when OpenSSL::PKey::EC key given' do
|
292
|
-
let(:public_key_or_secret) { public_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i }
|
293
|
-
it_behaves_like :success_signature_verification
|
294
|
-
end
|
295
|
-
|
296
|
-
context 'when JSON::JWK key given' do
|
297
|
-
let(:public_key_or_secret) { JSON::JWK.new public_key(:ecdsa, digest_length: algorithm.to_s[2,3].to_i) }
|
298
|
-
it_behaves_like :success_signature_verification
|
299
|
-
end
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
context 'when JSON::JWK::Set key given' do
|
304
|
-
subject { JSON::JWT.decode signed.to_s, jwks }
|
305
|
-
|
306
|
-
let(:alg) { :HS256 }
|
307
|
-
let(:kid) { 'kid' }
|
308
|
-
let(:jwks) do
|
309
|
-
jwk = JSON::JWK.new shared_secret, kid: kid
|
310
|
-
JSON::JWK::Set.new jwk, JSON::JWK.new('another')
|
311
|
-
end
|
312
|
-
let(:signed) { jws.sign!(jwks) }
|
313
|
-
|
314
|
-
context 'when jwk is found by given kid' do
|
315
|
-
before { jws.kid = kid }
|
316
|
-
it { should == signed }
|
317
|
-
end
|
318
|
-
|
319
|
-
context 'otherwise' do
|
320
|
-
it do
|
321
|
-
expect do
|
322
|
-
subject
|
323
|
-
end.to raise_error JSON::JWK::Set::KidNotFound
|
324
|
-
end
|
325
|
-
end
|
326
|
-
end
|
327
|
-
|
328
|
-
describe 'unknown algorithm' do
|
329
|
-
let(:alg) { :unknown }
|
330
|
-
it do
|
331
|
-
expect do
|
332
|
-
jws.verify! 'key'
|
333
|
-
end.to raise_error JSON::JWS::UnexpectedAlgorithm
|
334
|
-
end
|
335
|
-
end
|
336
|
-
end
|
337
|
-
|
338
|
-
describe '#to_json' do
|
339
|
-
let(:alg) { :RS256 }
|
340
|
-
let(:private_key_or_secret) { private_key }
|
341
|
-
|
342
|
-
context 'as default' do
|
343
|
-
it 'should JSONize payload' do
|
344
|
-
jws.to_json.should == claims.to_json
|
345
|
-
end
|
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
|
353
|
-
|
354
|
-
context 'when syntax option given' do
|
355
|
-
context 'when general' do
|
356
|
-
it 'should return General JWS JSON Serialization' do
|
357
|
-
signed.to_json(syntax: :general).should == {
|
358
|
-
payload: Base64.urlsafe_encode64(claims.to_json, padding: false),
|
359
|
-
signatures: [{
|
360
|
-
protected: Base64.urlsafe_encode64(signed.header.to_json, padding: false),
|
361
|
-
signature: Base64.urlsafe_encode64(signed.signature, padding: false)
|
362
|
-
}]
|
363
|
-
}.to_json
|
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
|
376
|
-
|
377
|
-
context 'when not signed yet' do
|
378
|
-
it 'should not fail' do
|
379
|
-
jws.to_json(syntax: :general).should == {
|
380
|
-
payload: Base64.urlsafe_encode64(claims.to_json, padding: false),
|
381
|
-
signatures: [{
|
382
|
-
protected: Base64.urlsafe_encode64(jws.header.to_json, padding: false),
|
383
|
-
signature: Base64.urlsafe_encode64('', padding: false)
|
384
|
-
}]
|
385
|
-
}.to_json
|
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
|
398
|
-
end
|
399
|
-
end
|
400
|
-
|
401
|
-
context 'when flattened' do
|
402
|
-
it 'should return Flattened JWS JSON Serialization' do
|
403
|
-
signed.to_json(syntax: :flattened).should == {
|
404
|
-
protected: Base64.urlsafe_encode64(signed.header.to_json, padding: false),
|
405
|
-
payload: Base64.urlsafe_encode64(claims.to_json, padding: false),
|
406
|
-
signature: Base64.urlsafe_encode64(signed.signature, padding: false)
|
407
|
-
}.to_json
|
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
|
418
|
-
|
419
|
-
context 'when not signed yet' do
|
420
|
-
it 'should not fail' do
|
421
|
-
jws.to_json(syntax: :flattened).should == {
|
422
|
-
protected: Base64.urlsafe_encode64(jws.header.to_json, padding: false),
|
423
|
-
payload: Base64.urlsafe_encode64(claims.to_json, padding: false),
|
424
|
-
signature: Base64.urlsafe_encode64('', padding: false)
|
425
|
-
}.to_json
|
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
|
436
|
-
end
|
437
|
-
end
|
438
|
-
end
|
439
|
-
end
|
440
|
-
end
|