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.
- checksums.yaml +5 -5
- data/.github/FUNDING.yml +3 -0
- data/.github/workflows/spec.yml +31 -0
- data/.gitmodules +1 -1
- data/CHANGELOG.md +17 -0
- data/Gemfile +1 -1
- data/README.md +11 -2
- data/VERSION +1 -1
- data/json-jwt.gemspec +10 -5
- data/lib/json/jose.rb +22 -11
- data/lib/json/jwe.rb +55 -38
- data/lib/json/jwk/jwkizable.rb +13 -11
- data/lib/json/jwk/set/fetcher.rb +93 -0
- data/lib/json/jwk/set.rb +7 -1
- data/lib/json/jwk.rb +62 -34
- data/lib/json/jws.rb +38 -35
- data/lib/json/jwt.rb +43 -17
- metadata +55 -56
- data/.travis.yml +0 -11
- 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 -311
- 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 -324
- data/spec/json/jwt_spec.rb +0 -496
- data/spec/spec_helper.rb +0 -28
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 == UrlSafeBase64.encode64(public_key.e.to_s(2)) }
|
|
83
|
-
its(:n) { jwk[:n].should == UrlSafeBase64.encode64(public_key.n.to_s(2)) }
|
|
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,324 +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(:jws) { JSON::JWS.new jwt }
|
|
11
|
-
let(:signed) { jws.sign! private_key_or_secret }
|
|
12
|
-
let(:decoded) { JSON::JWT.decode signed.to_s, public_key_or_secret }
|
|
13
|
-
let(:claims) do
|
|
14
|
-
{
|
|
15
|
-
iss: 'joe',
|
|
16
|
-
exp: 1300819380,
|
|
17
|
-
:'http://example.com/is_root' => true
|
|
18
|
-
}
|
|
19
|
-
end
|
|
20
|
-
let(:expected_signature) do
|
|
21
|
-
{
|
|
22
|
-
:HS256 => 'DyuTgO2Ggb5nrhkkhI-RjVYIBe3o8oL4ijkAn94YPxQ',
|
|
23
|
-
:HS384 => 'a5-7rr61TG8Snv9xxJ7l064ky-SCq1Mswe9t8HEorvoc_nnfIeUy9WQCLMIli34R',
|
|
24
|
-
:HS512 => 'ce-GlHDaNwaHfmAFRGp3QPPKvrpruTug2hC1bf6yNlbuvkMwJw2jFZgq_4wmIPetRdiBy7XFq7rrtmw1Im7tmQ',
|
|
25
|
-
:RS256 => 'E5VELqAdla2Bx1axc9KFxO0EiCr0Mw6HPYX070qGQ8zA_XmyxGPUZLyyWU_6Cn399W-oYBWO2ynLlr8pqqjP3jXevyCeYeGRVN0HzLYiBebEugNnc3hevr7WV2UzfksWRA-Ux2bDv2sz9p_LGbL33wWNxGDvIlpDyZUul_a48nCipS0riBjkTLTSE8dfBxQTXEF5GEUUu99ot6aBLzUhc25nHXSXogXF6MHK-hAcE7f4v-vJ0lbPbHLVGUopIoxoqe4XjoBpzE5UvhrVl5LYbdjbyJhu5ZIA8GLsgwtUFh3dfdIechORoR3k5NSFSv8157bAEa8t4iwgWD2MSNSQnw',
|
|
26
|
-
:RS384 => 'lT5JbytGKgG9QrwkJuxgw7UjmN9tjkEQW9pVGR2XnKEdC0_wLNIzAmT-jTwyMDGBLUkWO7opDOP6Xy6_DOTg58k9PwVkyQzrLnmxJMEng2Q-aMqcitRSIvUk3DPy8kemp8yUPls9NzWmByM2GoUVHbDsR0r-tZN-g_9QYev32mvMhjMr30JI5S2xiRjc9m2GAaXMOQmNTovJgV4bgCp4UjruCrA0BD1JJwDqKYoR_YYr_ALcVjD_LUgy80udJvbi8MAYJVUf0QYtQDrX2wnT_-eiiWjD5XafLuXEQVDRh-v2MKAwdvtXMq5cZ08Zjl2SyHxJ3OqhEeWPvYGltxZh_A',
|
|
27
|
-
:RS512 => 'EHeGM2Mo3ghhUfSB99AlREehrbC6OPE-nYL_rwf88ysTnJ8L1QQ0UuCrXq4SpRutGLK_bYTK3ZALvFRPoOgK_g0QWmqv6qjQRU_QTxoq8y8APP-IgKKDuIiGH6daBV2rAPLDReqYNKsKjmTvZJo2c0a0e_WZkkj_ZwpgjTG3v0gW9lbDAzLJDz18eqtR4ZO7JTu_fyNrUrNk-w2_wpxSsn9sygIMp0lKE0_pt0b01fz3gjTDjlltU0cKSalUp4geaBDH7QRcexrolIctdQFbNKTXQxoigxD3NLNkKGH7f6A8KZdcOm8AnEjullcZs8_OWGnW43p1qrxoBRSivb9pqQ'
|
|
28
|
-
}
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
shared_examples_for :jwt_with_alg do
|
|
32
|
-
it { should == jwt }
|
|
33
|
-
its(:header) { should == jwt.header }
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
context 'before sign' do
|
|
37
|
-
subject { jws }
|
|
38
|
-
it_behaves_like :jwt_with_alg
|
|
39
|
-
its(:signature) { should be_nil }
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
describe '#content_type' do
|
|
43
|
-
it do
|
|
44
|
-
jws.content_type.should == 'application/jose'
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
describe '#sign!' do
|
|
49
|
-
shared_examples_for :generate_expected_signature do
|
|
50
|
-
it do
|
|
51
|
-
UrlSafeBase64.encode64(signed.signature).should == expected_signature[alg]
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
subject { signed }
|
|
55
|
-
|
|
56
|
-
[:HS256, :HS384, :HS512].each do |algorithm|
|
|
57
|
-
describe algorithm do
|
|
58
|
-
let(:alg) { algorithm }
|
|
59
|
-
|
|
60
|
-
context 'when String key given' do
|
|
61
|
-
let(:private_key_or_secret) { shared_secret }
|
|
62
|
-
it_behaves_like :jwt_with_alg
|
|
63
|
-
it_behaves_like :generate_expected_signature
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
context 'when JSON::JWK key given' do
|
|
67
|
-
let(:private_key_or_secret) { JSON::JWK.new shared_secret }
|
|
68
|
-
it_behaves_like :jwt_with_alg
|
|
69
|
-
it_behaves_like :generate_expected_signature
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
[:RS256, :RS384, :RS512].each do |algorithm|
|
|
75
|
-
describe algorithm do
|
|
76
|
-
let(:alg) { algorithm }
|
|
77
|
-
|
|
78
|
-
context 'when OpenSSL::PKey::RSA key given' do
|
|
79
|
-
let(:private_key_or_secret) { private_key }
|
|
80
|
-
it_behaves_like :jwt_with_alg
|
|
81
|
-
it_behaves_like :generate_expected_signature
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
context 'when JSON::JWK key given' do
|
|
85
|
-
let(:private_key_or_secret) { JSON::JWK.new private_key }
|
|
86
|
-
it_behaves_like :jwt_with_alg
|
|
87
|
-
it_behaves_like :generate_expected_signature
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
[:ES256, :ES384, :ES512].each do |algorithm|
|
|
93
|
-
describe algorithm do
|
|
94
|
-
let(:alg) { algorithm }
|
|
95
|
-
|
|
96
|
-
shared_examples_for :self_verifiable do
|
|
97
|
-
it 'should be self-verifiable' do
|
|
98
|
-
expect do
|
|
99
|
-
JSON::JWT.decode(
|
|
100
|
-
JSON::JWT.new(claims).sign(
|
|
101
|
-
private_key_or_secret, algorithm
|
|
102
|
-
).to_s, public_key_or_secret
|
|
103
|
-
)
|
|
104
|
-
end.not_to raise_error
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
context 'when OpenSSL::PKey::EC key given' do
|
|
109
|
-
let(:private_key_or_secret) { private_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i }
|
|
110
|
-
let(:public_key_or_secret) { public_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i }
|
|
111
|
-
it_behaves_like :jwt_with_alg
|
|
112
|
-
it_behaves_like :self_verifiable
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
context 'when JSON::JWK key given' do
|
|
116
|
-
let(:private_key_or_secret) { JSON::JWK.new(private_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i) }
|
|
117
|
-
let(:public_key_or_secret) { JSON::JWK.new(public_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i) }
|
|
118
|
-
it_behaves_like :jwt_with_alg
|
|
119
|
-
it_behaves_like :self_verifiable
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
context 'when JSON::JWK::Set key given' do
|
|
125
|
-
let(:alg) { :HS256 }
|
|
126
|
-
let(:kid) { 'kid' }
|
|
127
|
-
let(:jwks) do
|
|
128
|
-
jwk = JSON::JWK.new shared_secret, kid: kid
|
|
129
|
-
JSON::JWK::Set.new jwk, JSON::JWK.new('another')
|
|
130
|
-
end
|
|
131
|
-
let(:signed) { jws.sign!(jwks) }
|
|
132
|
-
|
|
133
|
-
context 'when jwk is found by given kid' do
|
|
134
|
-
before { jws.kid = kid }
|
|
135
|
-
it { should == jws.sign!('secret') }
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
context 'otherwise' do
|
|
139
|
-
it do
|
|
140
|
-
expect do
|
|
141
|
-
subject
|
|
142
|
-
end.to raise_error JSON::JWK::Set::KidNotFound
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
describe 'unknown algorithm' do
|
|
148
|
-
let(:alg) { :unknown }
|
|
149
|
-
it do
|
|
150
|
-
expect do
|
|
151
|
-
jws.sign! 'key'
|
|
152
|
-
end.to raise_error JSON::JWS::UnexpectedAlgorithm
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
describe '#verify!' do
|
|
158
|
-
shared_examples_for :success_signature_verification do
|
|
159
|
-
it do
|
|
160
|
-
expect { decoded }.not_to raise_error
|
|
161
|
-
decoded.should be_a JSON::JWT
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
describe 'header' do
|
|
165
|
-
let(:header) { decoded.header }
|
|
166
|
-
it 'should be parsed successfully' do
|
|
167
|
-
header[:typ].should == 'JWT'
|
|
168
|
-
header[:alg].should == alg.to_s
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
describe 'claims' do
|
|
173
|
-
it 'should be parsed successfully' do
|
|
174
|
-
decoded[:iss].should == 'joe'
|
|
175
|
-
decoded[:exp].should == 1300819380
|
|
176
|
-
decoded[:'http://example.com/is_root'] == true
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
end
|
|
180
|
-
subject { decoded }
|
|
181
|
-
|
|
182
|
-
[:HS256, :HS384, :HS512].each do |algorithm|
|
|
183
|
-
describe algorithm do
|
|
184
|
-
let(:alg) { algorithm }
|
|
185
|
-
let(:private_key_or_secret) { shared_secret }
|
|
186
|
-
|
|
187
|
-
context 'when String key given' do
|
|
188
|
-
let(:public_key_or_secret) { shared_secret }
|
|
189
|
-
it_behaves_like :success_signature_verification
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
context 'when JSON::JWK key given' do
|
|
193
|
-
let(:public_key_or_secret) { JSON::JWK.new shared_secret }
|
|
194
|
-
it_behaves_like :success_signature_verification
|
|
195
|
-
end
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
[:RS256, :RS384, :RS512].each do |algorithm|
|
|
200
|
-
describe algorithm do
|
|
201
|
-
let(:alg) { algorithm }
|
|
202
|
-
let(:private_key_or_secret) { private_key }
|
|
203
|
-
|
|
204
|
-
context 'when OpenSSL::PKey::RSA key given' do
|
|
205
|
-
let(:public_key_or_secret) { public_key }
|
|
206
|
-
it_behaves_like :success_signature_verification
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
context 'when JSON::JWK key given' do
|
|
210
|
-
let(:public_key_or_secret) { JSON::JWK.new public_key }
|
|
211
|
-
it_behaves_like :success_signature_verification
|
|
212
|
-
end
|
|
213
|
-
end
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
[:ES256, :ES384, :ES512].each do |algorithm|
|
|
217
|
-
describe algorithm do
|
|
218
|
-
let(:alg) { algorithm }
|
|
219
|
-
let(:private_key_or_secret) { private_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i }
|
|
220
|
-
|
|
221
|
-
context 'when OpenSSL::PKey::EC key given' do
|
|
222
|
-
let(:public_key_or_secret) { public_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i }
|
|
223
|
-
it_behaves_like :success_signature_verification
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
context 'when JSON::JWK key given' do
|
|
227
|
-
let(:public_key_or_secret) { JSON::JWK.new public_key(:ecdsa, digest_length: algorithm.to_s[2,3].to_i) }
|
|
228
|
-
it_behaves_like :success_signature_verification
|
|
229
|
-
end
|
|
230
|
-
end
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
context 'when JSON::JWK::Set key given' do
|
|
234
|
-
subject { JSON::JWT.decode signed.to_s, jwks }
|
|
235
|
-
|
|
236
|
-
let(:alg) { :HS256 }
|
|
237
|
-
let(:kid) { 'kid' }
|
|
238
|
-
let(:jwks) do
|
|
239
|
-
jwk = JSON::JWK.new shared_secret, kid: kid
|
|
240
|
-
JSON::JWK::Set.new jwk, JSON::JWK.new('another')
|
|
241
|
-
end
|
|
242
|
-
let(:signed) { jws.sign!(jwks) }
|
|
243
|
-
|
|
244
|
-
context 'when jwk is found by given kid' do
|
|
245
|
-
before { jws.kid = kid }
|
|
246
|
-
it { should == signed }
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
context 'otherwise' do
|
|
250
|
-
it do
|
|
251
|
-
expect do
|
|
252
|
-
subject
|
|
253
|
-
end.to raise_error JSON::JWK::Set::KidNotFound
|
|
254
|
-
end
|
|
255
|
-
end
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
describe 'unknown algorithm' do
|
|
259
|
-
let(:alg) { :unknown }
|
|
260
|
-
it do
|
|
261
|
-
expect do
|
|
262
|
-
jws.verify! 'key'
|
|
263
|
-
end.to raise_error JSON::JWS::UnexpectedAlgorithm
|
|
264
|
-
end
|
|
265
|
-
end
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
describe '#to_json' do
|
|
269
|
-
let(:alg) { :RS256 }
|
|
270
|
-
let(:private_key_or_secret) { private_key }
|
|
271
|
-
|
|
272
|
-
context 'as default' do
|
|
273
|
-
it 'should JSONize payload' do
|
|
274
|
-
jws.to_json.should == claims.to_json
|
|
275
|
-
end
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
context 'when syntax option given' do
|
|
279
|
-
context 'when general' do
|
|
280
|
-
it 'should return General JWS JSON Serialization' do
|
|
281
|
-
signed.to_json(syntax: :general).should == {
|
|
282
|
-
payload: UrlSafeBase64.encode64(claims.to_json),
|
|
283
|
-
signatures: [{
|
|
284
|
-
protected: UrlSafeBase64.encode64(signed.header.to_json),
|
|
285
|
-
signature: UrlSafeBase64.encode64(signed.signature)
|
|
286
|
-
}]
|
|
287
|
-
}.to_json
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
context 'when not signed yet' do
|
|
291
|
-
it 'should not fail' do
|
|
292
|
-
jws.to_json(syntax: :general).should == {
|
|
293
|
-
payload: UrlSafeBase64.encode64(claims.to_json),
|
|
294
|
-
signatures: [{
|
|
295
|
-
protected: UrlSafeBase64.encode64(jws.header.to_json),
|
|
296
|
-
signature: UrlSafeBase64.encode64('')
|
|
297
|
-
}]
|
|
298
|
-
}.to_json
|
|
299
|
-
end
|
|
300
|
-
end
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
context 'when flattened' do
|
|
304
|
-
it 'should return Flattened JWS JSON Serialization' do
|
|
305
|
-
signed.to_json(syntax: :flattened).should == {
|
|
306
|
-
protected: UrlSafeBase64.encode64(signed.header.to_json),
|
|
307
|
-
payload: UrlSafeBase64.encode64(claims.to_json),
|
|
308
|
-
signature: UrlSafeBase64.encode64(signed.signature)
|
|
309
|
-
}.to_json
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
context 'when not signed yet' do
|
|
313
|
-
it 'should not fail' do
|
|
314
|
-
jws.to_json(syntax: :flattened).should == {
|
|
315
|
-
protected: UrlSafeBase64.encode64(jws.header.to_json),
|
|
316
|
-
payload: UrlSafeBase64.encode64(claims.to_json),
|
|
317
|
-
signature: UrlSafeBase64.encode64('')
|
|
318
|
-
}.to_json
|
|
319
|
-
end
|
|
320
|
-
end
|
|
321
|
-
end
|
|
322
|
-
end
|
|
323
|
-
end
|
|
324
|
-
end
|