openid_connect 0.6.1 → 0.7.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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/README.rdoc +3 -1
- data/VERSION +1 -1
- data/lib/openid_connect/access_token.rb +1 -2
- data/lib/openid_connect/client.rb +2 -6
- data/lib/openid_connect/client/registrar.rb +59 -123
- data/lib/openid_connect/discovery.rb +0 -2
- data/lib/openid_connect/discovery/provider.rb +3 -1
- data/lib/openid_connect/discovery/provider/config/response.rb +57 -78
- data/lib/openid_connect/request_object.rb +1 -8
- data/lib/openid_connect/request_object/{user_info.rb → userinfo.rb} +0 -0
- data/lib/openid_connect/response_object/id_token.rb +1 -1
- data/lib/openid_connect/response_object/userinfo.rb +3 -0
- data/lib/openid_connect/response_object/{user_info → userinfo}/open_id.rb +7 -6
- data/lib/openid_connect/response_object/{user_info → userinfo}/open_id/address.rb +0 -0
- data/openid_connect.gemspec +2 -2
- data/spec/helpers/webmock_helper.rb +2 -1
- data/spec/mock_response/discovery/config.json +3 -2
- data/spec/mock_response/public_keys/{jwk.json → jwks.json} +1 -1
- data/spec/mock_response/{user_info → userinfo}/openid.json +0 -0
- data/spec/openid_connect/access_token_spec.rb +7 -6
- data/spec/openid_connect/client/registrar_spec.rb +82 -207
- data/spec/openid_connect/client_spec.rb +2 -2
- data/spec/openid_connect/discovery/provider/config/response_spec.rb +53 -286
- data/spec/openid_connect/discovery/provider/config_spec.rb +11 -12
- data/spec/openid_connect/discovery/provider_spec.rb +1 -1
- data/spec/openid_connect/request_object_spec.rb +4 -4
- data/spec/openid_connect/response_object/id_token_spec.rb +4 -4
- data/spec/openid_connect/response_object/user_info/open_id_spec.rb +1 -0
- metadata +17 -20
- data/Gemfile.lock +0 -102
- data/lib/openid_connect/response_object/user_info.rb +0 -3
- data/spec/mock_response/public_keys/x509.pem +0 -21
@@ -19,11 +19,11 @@ describe OpenIDConnect::Client do
|
|
19
19
|
end
|
20
20
|
its(:authorization_uri) { should include 'https://server.example.com/oauth2/authorize' }
|
21
21
|
its(:authorization_uri) { should include 'scope=openid' }
|
22
|
-
its(:
|
22
|
+
its(:userinfo_uri) { should == 'https://server.example.com/userinfo' }
|
23
23
|
end
|
24
24
|
|
25
25
|
context 'otherwise' do
|
26
|
-
[:authorization_uri, :
|
26
|
+
[:authorization_uri, :userinfo_uri].each do |endpoint|
|
27
27
|
describe endpoint do
|
28
28
|
it do
|
29
29
|
expect { client.send endpoint }.to raise_error 'No Host Info'
|
@@ -4,311 +4,78 @@ describe OpenIDConnect::Discovery::Provider::Config::Response do
|
|
4
4
|
let :instance do
|
5
5
|
OpenIDConnect::Discovery::Provider::Config::Response.new attributes
|
6
6
|
end
|
7
|
-
let :
|
8
|
-
|
7
|
+
let :jwks_uri do
|
8
|
+
'https://server.example.com/jwks.json'
|
9
9
|
end
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
let :minimum_attributes do
|
11
|
+
{
|
12
|
+
issuer: 'https://server.example.com',
|
13
|
+
jwks_uri: jwks_uri,
|
14
|
+
response_types_supported: [
|
15
|
+
:code, :id_token, 'token id_token'
|
16
|
+
],
|
17
|
+
subject_types_supported: [
|
18
|
+
:public, :pairwise
|
19
|
+
],
|
20
|
+
id_token_signing_alg_values_supported: [
|
21
|
+
:RS256
|
22
|
+
]
|
14
23
|
}
|
24
|
+
end
|
25
|
+
let :attributes do
|
26
|
+
minimum_attributes
|
27
|
+
end
|
28
|
+
subject { instance }
|
15
29
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
30
|
+
context 'when required attributes missing' do
|
31
|
+
let :attributes do
|
32
|
+
{}
|
20
33
|
end
|
34
|
+
it { should_not be_valid }
|
35
|
+
end
|
21
36
|
|
22
|
-
|
37
|
+
describe '#as_json' do
|
38
|
+
subject { instance.as_json }
|
39
|
+
it { should == minimum_attributes }
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#validate!' do
|
43
|
+
context 'when required attributes missing' do
|
23
44
|
let :attributes do
|
24
|
-
{
|
45
|
+
{}
|
25
46
|
end
|
26
47
|
it do
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
should_not include :user_info_endpoint
|
48
|
+
expect do
|
49
|
+
instance.validate!
|
50
|
+
end.to raise_error OpenIDConnect::ValidationFailed
|
31
51
|
end
|
32
52
|
end
|
33
53
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
context "when #{key} given" do
|
40
|
-
let :attributes do
|
41
|
-
{key => [:x, :y]}
|
42
|
-
end
|
43
|
-
it do
|
44
|
-
should include key.to_s.sub('user_info', 'userinfo').to_sym
|
45
|
-
end
|
46
|
-
it do
|
47
|
-
should_not include key
|
48
|
-
end
|
54
|
+
context 'otherwise' do
|
55
|
+
it do
|
56
|
+
expect do
|
57
|
+
instance.validate!
|
58
|
+
end.not_to raise_error OpenIDConnect::ValidationFailed
|
49
59
|
end
|
50
60
|
end
|
51
61
|
end
|
52
62
|
|
53
|
-
describe '#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
{
|
58
|
-
x509_url: x509_url,
|
59
|
-
x509_encryption_url: x509_encryption_url,
|
60
|
-
jwk_url: jwk_url,
|
61
|
-
jwk_encryption_url: jwk_encryption_url
|
62
|
-
}.delete_if do |key, value|
|
63
|
-
value.nil?
|
64
|
-
end
|
65
|
-
end
|
66
|
-
let(:x509_url) { nil }
|
67
|
-
let(:x509_encryption_url) { nil }
|
68
|
-
let(:jwk_url) { nil }
|
69
|
-
let(:jwk_encryption_url) { nil }
|
70
|
-
|
71
|
-
context 'when x509_url is given' do
|
72
|
-
let(:x509_url) { 'http://provider.example.com/x509.pem' }
|
73
|
-
|
74
|
-
context 'when x509_encryption_url is given' do
|
75
|
-
let(:x509_encryption_url) { 'http://provider.example.com/x509_encryption.pem' }
|
76
|
-
|
77
|
-
it 'should fetch signing_key from x509_url' do
|
78
|
-
mock_json :get, x509_url, 'public_keys/x509', format: :pem do
|
79
|
-
config.signing_key
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
it 'should fetch encryption_key from x509_encryption_url' do
|
84
|
-
mock_json :get, x509_encryption_url, 'public_keys/x509', format: :pem do
|
85
|
-
config.encryption_key
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
context 'when jwk_encryption_url is given' do
|
91
|
-
let(:jwk_encryption_url) { 'http://provider.example.com/jwk_encryption.json' }
|
92
|
-
|
93
|
-
it 'should fetch signing_key from x509_url' do
|
94
|
-
mock_json :get, x509_url, 'public_keys/x509', format: :pem do
|
95
|
-
config.signing_key
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'should fetch encryption_key from jwk_encryption_url' do
|
100
|
-
mock_json :get, jwk_encryption_url, 'public_keys/jwk' do
|
101
|
-
config.encryption_key
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
context 'when both x509_encryption_url and jwk_encryption_url are given' do
|
107
|
-
let(:x509_encryption_url) { 'http://provider.example.com/x509_encryption.pem' }
|
108
|
-
let(:jwk_encryption_url) { 'http://provider.example.com/jwk_encryption.json' }
|
109
|
-
|
110
|
-
it 'should fetch signing_key from x509_url' do
|
111
|
-
mock_json :get, x509_url, 'public_keys/x509', format: :pem do
|
112
|
-
config.signing_key
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'should fetch encryption_key from x509_encryption_url' do
|
117
|
-
mock_json :get, x509_encryption_url, 'public_keys/x509', format: :pem do
|
118
|
-
config.encryption_key
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
context 'when neither x509_encryption_url nor jwk_encryption_url are given' do
|
124
|
-
it 'should fetch signing_key from x509_url' do
|
125
|
-
mock_json :get, x509_url, 'public_keys/x509', format: :pem do
|
126
|
-
config.signing_key
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
it 'should fetch encryption_key from x509_encryption_url' do
|
131
|
-
mock_json :get, x509_url, 'public_keys/x509', format: :pem do
|
132
|
-
config.encryption_key
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
context 'when jwk_url is given' do
|
139
|
-
let(:jwk_url) { 'http://provider.example.com/jwk.json' }
|
140
|
-
|
141
|
-
context 'when x509_encryption_url is given' do
|
142
|
-
let(:x509_encryption_url) { 'http://provider.example.com/x509_encryption.pem' }
|
143
|
-
|
144
|
-
it 'should fetch signing_key from jwk_url' do
|
145
|
-
mock_json :get, jwk_url, 'public_keys/jwk' do
|
146
|
-
config.signing_key
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
it 'should fetch encryption_key from x509_encryption_url' do
|
151
|
-
mock_json :get, x509_encryption_url, 'public_keys/x509', format: :pem do
|
152
|
-
config.encryption_key
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
context 'when jwk_encryption_url is given' do
|
158
|
-
let(:jwk_encryption_url) { 'http://provider.example.com/jwk_encryption.json' }
|
159
|
-
|
160
|
-
it 'should fetch signing_key from jwk_url' do
|
161
|
-
mock_json :get, jwk_url, 'public_keys/jwk' do
|
162
|
-
config.signing_key
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
it 'should fetch encryption_key from jwk_encryption_url' do
|
167
|
-
mock_json :get, jwk_encryption_url, 'public_keys/jwk' do
|
168
|
-
config.encryption_key
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
context 'when both x509_encryption_url and jwk_encryption_url are given' do
|
174
|
-
let(:x509_encryption_url) { 'http://provider.example.com/x509_encryption.pem' }
|
175
|
-
let(:jwk_encryption_url) { 'http://provider.example.com/jwk_encryption.json' }
|
176
|
-
|
177
|
-
it 'should fetch signing_key from jwk_url' do
|
178
|
-
mock_json :get, jwk_url, 'public_keys/jwk' do
|
179
|
-
config.signing_key
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
it 'should fetch encryption_key from x509_encryption_url' do
|
184
|
-
mock_json :get, x509_encryption_url, 'public_keys/x509', format: :pem do
|
185
|
-
config.encryption_key
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
context 'when neither x509_encryption_url nor jwk_encryption_url are given' do
|
191
|
-
it 'should fetch signing_key from jwk_url' do
|
192
|
-
mock_json :get, jwk_url, 'public_keys/jwk' do
|
193
|
-
config.signing_key
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
it 'should fetch encryption_key from x509_encryption_url' do
|
198
|
-
mock_json :get, jwk_url, 'public_keys/jwk' do
|
199
|
-
config.encryption_key
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
context 'when both x509_url and jwk_url are given' do
|
206
|
-
let(:x509_url) { 'http://provider.example.com/cert.pem' }
|
207
|
-
let(:jwk_url) { 'http://provider.example.com/jwk.json' }
|
208
|
-
|
209
|
-
context 'when x509_encryption_url is given' do
|
210
|
-
let(:x509_encryption_url) { 'http://provider.example.com/x509_encryption.pem' }
|
211
|
-
|
212
|
-
it 'should fetch signing_key from x509_url' do
|
213
|
-
mock_json :get, x509_url, 'public_keys/x509', format: :pem do
|
214
|
-
config.signing_key
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
it 'should fetch encryption_key from x509_encryption_url' do
|
219
|
-
mock_json :get, x509_encryption_url, 'public_keys/x509', format: :pem do
|
220
|
-
config.encryption_key
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
context 'when jwk_encryption_url is given' do
|
226
|
-
let(:jwk_encryption_url) { 'http://provider.example.com/jwk_encryption.json' }
|
227
|
-
|
228
|
-
it 'should fetch signing_key from x509_url' do
|
229
|
-
mock_json :get, x509_url, 'public_keys/x509', format: :pem do
|
230
|
-
config.signing_key
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
it 'should fetch encryption_key from jwk_encryption_url' do
|
235
|
-
mock_json :get, jwk_encryption_url, 'public_keys/jwk' do
|
236
|
-
config.encryption_key
|
237
|
-
end
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
context 'when both x509_encryption_url and jwk_encryption_url are given' do
|
242
|
-
let(:x509_encryption_url) { 'http://provider.example.com/x509_encryption.pem' }
|
243
|
-
let(:jwk_encryption_url) { 'http://provider.example.com/jwk_encryption.json' }
|
244
|
-
|
245
|
-
it 'should fetch signing_key from x509_url' do
|
246
|
-
mock_json :get, x509_url, 'public_keys/x509', format: :pem do
|
247
|
-
config.signing_key
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
it 'should fetch encryption_key from x509_encryption_url' do
|
252
|
-
mock_json :get, x509_encryption_url, 'public_keys/x509', format: :pem do
|
253
|
-
config.encryption_key
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
context 'when neither x509_encryption_url nor jwk_encryption_url are given' do
|
259
|
-
it 'should fetch signing_key from x509_url' do
|
260
|
-
mock_json :get, x509_url, 'public_keys/x509', format: :pem do
|
261
|
-
config.signing_key
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
it 'should fetch encryption_key from x509_url' do
|
266
|
-
mock_json :get, x509_url, 'public_keys/x509', format: :pem do
|
267
|
-
config.encryption_key
|
268
|
-
end
|
269
|
-
end
|
63
|
+
describe '#jwks' do
|
64
|
+
it do
|
65
|
+
jwks = mock_json :get, jwks_uri, 'public_keys/jwks' do
|
66
|
+
instance.jwks
|
270
67
|
end
|
68
|
+
jwks.should be_instance_of JSON::JWK::Set
|
271
69
|
end
|
70
|
+
end
|
272
71
|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
it 'should fetch encryption_key from x509_encryption_url' do
|
279
|
-
mock_json :get, x509_encryption_url, 'public_keys/x509', format: :pem do
|
280
|
-
config.encryption_key
|
281
|
-
end
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
|
-
context 'when jwk_encryption_url is given' do
|
286
|
-
let(:jwk_encryption_url) { 'http://provider.example.com/jwk_encryption.json' }
|
287
|
-
its(:signing_key) { should be_nil }
|
288
|
-
|
289
|
-
it 'should fetch encryption_key from jwk_encryption_url' do
|
290
|
-
mock_json :get, jwk_encryption_url, 'public_keys/jwk' do
|
291
|
-
config.encryption_key
|
292
|
-
end
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
|
-
context 'when both x509_encryption_url and jwk_encryption_url are given' do
|
297
|
-
let(:x509_encryption_url) { 'http://provider.example.com/x509_encryption.pem' }
|
298
|
-
let(:jwk_encryption_url) { 'http://provider.example.com/jwk_encryption.json' }
|
299
|
-
its(:signing_key) { should be_nil }
|
300
|
-
|
301
|
-
it 'should fetch encryption_key from x509_encryption_url' do
|
302
|
-
mock_json :get, x509_encryption_url, 'public_keys/x509', format: :pem do
|
303
|
-
config.encryption_key
|
304
|
-
end
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
context 'when neither x509_encryption_url nor jwk_encryption_url are given' do
|
309
|
-
its(:signing_key) { should be_nil }
|
310
|
-
its(:encryption_key) { should be_nil }
|
72
|
+
describe '#public_keys' do
|
73
|
+
it do
|
74
|
+
public_keys = mock_json :get, jwks_uri, 'public_keys/jwks' do
|
75
|
+
instance.public_keys
|
311
76
|
end
|
77
|
+
public_keys.should be_instance_of Array
|
78
|
+
public_keys.first.should be_instance_of OpenSSL::PKey::RSA
|
312
79
|
end
|
313
80
|
end
|
314
81
|
end
|
@@ -2,28 +2,27 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe OpenIDConnect::Discovery::Provider::Config do
|
4
4
|
let(:provider) { 'https://connect-op.heroku.com' }
|
5
|
-
let(:endpoint) {
|
5
|
+
let(:endpoint) { 'https://connect-op.heroku.com/.well-known/openid-configuration' }
|
6
6
|
|
7
7
|
describe 'discover!' do
|
8
8
|
it 'should setup given attributes' do
|
9
9
|
mock_json :get, endpoint, 'discovery/config' do
|
10
10
|
config = OpenIDConnect::Discovery::Provider::Config.discover! provider
|
11
11
|
config.should be_instance_of OpenIDConnect::Discovery::Provider::Config::Response
|
12
|
-
config.version.should == '3.0'
|
13
12
|
config.issuer.should == 'https://connect-op.heroku.com'
|
14
13
|
config.authorization_endpoint.should == 'https://connect-op.heroku.com/authorizations/new'
|
15
14
|
config.token_endpoint.should == 'https://connect-op.heroku.com/access_tokens'
|
16
|
-
config.
|
17
|
-
config.
|
15
|
+
config.userinfo_endpoint.should == 'https://connect-op.heroku.com/userinfo'
|
16
|
+
config.check_session_endpoint.should be_nil
|
18
17
|
config.end_session_endpoint.should be_nil
|
19
|
-
config.
|
20
|
-
config.x509_url.should == 'https://connect-op.heroku.com/cert.pem'
|
18
|
+
config.jwks_uri.should == 'https://connect-op.heroku.com/jwks.json'
|
21
19
|
config.registration_endpoint.should == 'https://connect-op.heroku.com/connect/client'
|
22
|
-
config.scopes_supported.should == [
|
23
|
-
config.response_types_supported.should == [
|
20
|
+
config.scopes_supported.should == ['openid', 'profile', 'email', 'address']
|
21
|
+
config.response_types_supported.should == ['code', 'token', 'id_token', 'code token', 'code id_token', 'id_token token']
|
24
22
|
config.acr_values_supported.should be_nil
|
25
|
-
config.subject_types_supported.should == [
|
26
|
-
config.claims_supported.should == [
|
23
|
+
config.subject_types_supported.should == ['public', 'pairwise']
|
24
|
+
config.claims_supported.should == ['sub', 'iss', 'name', 'email']
|
25
|
+
config.id_token_signing_alg_values_supported.should == ['RS256']
|
27
26
|
end
|
28
27
|
end
|
29
28
|
|
@@ -40,7 +39,7 @@ describe OpenIDConnect::Discovery::Provider::Config do
|
|
40
39
|
|
41
40
|
context 'when OP identifier includes custom port' do
|
42
41
|
let(:provider) { 'https://connect-op.heroku.com:8080' }
|
43
|
-
let(:endpoint) {
|
42
|
+
let(:endpoint) { 'https://connect-op.heroku.com:8080/.well-known/openid-configuration' }
|
44
43
|
|
45
44
|
it 'should construct well-known URI with given port' do
|
46
45
|
mock_json :get, endpoint, 'discovery/config' do
|
@@ -51,7 +50,7 @@ describe OpenIDConnect::Discovery::Provider::Config do
|
|
51
50
|
|
52
51
|
context 'when OP identifier includes path' do
|
53
52
|
let(:provider) { 'https://connect.openid4.us/abop' }
|
54
|
-
let(:endpoint) {
|
53
|
+
let(:endpoint) { 'https://connect.openid4.us/abop/.well-known/openid-configuration' }
|
55
54
|
|
56
55
|
it 'should construct well-known URI with given port' do
|
57
56
|
mock_json :get, endpoint, 'discovery/config' do
|
@@ -6,7 +6,7 @@ describe OpenIDConnect::Discovery::Provider do
|
|
6
6
|
let(:endpoint) { "https://#{host}/.well-known/webfinger" }
|
7
7
|
let(:query) do
|
8
8
|
{
|
9
|
-
rel: OpenIDConnect::Discovery::REL_VALUE,
|
9
|
+
rel: OpenIDConnect::Discovery::Provider::Issuer::REL_VALUE,
|
10
10
|
resource: resource
|
11
11
|
}
|
12
12
|
end
|
@@ -93,15 +93,15 @@ describe OpenIDConnect::RequestObject do
|
|
93
93
|
|
94
94
|
describe '#required?' do
|
95
95
|
it do
|
96
|
-
request_object.
|
97
|
-
request_object.
|
96
|
+
request_object.userinfo.required?(:name).should be_true
|
97
|
+
request_object.userinfo.optional?(:name).should be_false
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
101
|
describe '#optional' do
|
102
102
|
it do
|
103
|
-
request_object.
|
104
|
-
request_object.
|
103
|
+
request_object.userinfo.required?(:email).should be_false
|
104
|
+
request_object.userinfo.optional?(:email).should be_true
|
105
105
|
end
|
106
106
|
end
|
107
107
|
end
|