openid_connect 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/README.rdoc +3 -1
  4. data/VERSION +1 -1
  5. data/lib/openid_connect/access_token.rb +1 -2
  6. data/lib/openid_connect/client.rb +2 -6
  7. data/lib/openid_connect/client/registrar.rb +59 -123
  8. data/lib/openid_connect/discovery.rb +0 -2
  9. data/lib/openid_connect/discovery/provider.rb +3 -1
  10. data/lib/openid_connect/discovery/provider/config/response.rb +57 -78
  11. data/lib/openid_connect/request_object.rb +1 -8
  12. data/lib/openid_connect/request_object/{user_info.rb → userinfo.rb} +0 -0
  13. data/lib/openid_connect/response_object/id_token.rb +1 -1
  14. data/lib/openid_connect/response_object/userinfo.rb +3 -0
  15. data/lib/openid_connect/response_object/{user_info → userinfo}/open_id.rb +7 -6
  16. data/lib/openid_connect/response_object/{user_info → userinfo}/open_id/address.rb +0 -0
  17. data/openid_connect.gemspec +2 -2
  18. data/spec/helpers/webmock_helper.rb +2 -1
  19. data/spec/mock_response/discovery/config.json +3 -2
  20. data/spec/mock_response/public_keys/{jwk.json → jwks.json} +1 -1
  21. data/spec/mock_response/{user_info → userinfo}/openid.json +0 -0
  22. data/spec/openid_connect/access_token_spec.rb +7 -6
  23. data/spec/openid_connect/client/registrar_spec.rb +82 -207
  24. data/spec/openid_connect/client_spec.rb +2 -2
  25. data/spec/openid_connect/discovery/provider/config/response_spec.rb +53 -286
  26. data/spec/openid_connect/discovery/provider/config_spec.rb +11 -12
  27. data/spec/openid_connect/discovery/provider_spec.rb +1 -1
  28. data/spec/openid_connect/request_object_spec.rb +4 -4
  29. data/spec/openid_connect/response_object/id_token_spec.rb +4 -4
  30. data/spec/openid_connect/response_object/user_info/open_id_spec.rb +1 -0
  31. metadata +17 -20
  32. data/Gemfile.lock +0 -102
  33. data/lib/openid_connect/response_object/user_info.rb +0 -3
  34. 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(:user_info_uri) { should == 'https://server.example.com/user_info' }
22
+ its(:userinfo_uri) { should == 'https://server.example.com/userinfo' }
23
23
  end
24
24
 
25
25
  context 'otherwise' do
26
- [:authorization_uri, :user_info_uri].each do |endpoint|
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 :attributes do
8
- {}
7
+ let :jwks_uri do
8
+ 'https://server.example.com/jwks.json'
9
9
  end
10
-
11
- describe '#as_json' do
12
- subject {
13
- instance.as_json
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
- context 'when no attributes given' do
17
- it do
18
- should == {version: '3.0'}
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
- context 'when user_info_endpoint given' do
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
- {user_info_endpoint: 'https://server.example.com/user_info'}
45
+ {}
25
46
  end
26
47
  it do
27
- should include :userinfo_endpoint
28
- end
29
- it do
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
- :user_info_signing_alg_values_supported,
36
- :user_info_encryption_alg_values_supported,
37
- :user_info_encryption_enc_values_supported
38
- ].each do |key|
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 '#signing_key and #encryption_key' do
54
- subject { config }
55
- let(:config) { instance }
56
- let(:attributes) do
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
- context 'when neither x509_url nor jwk_url are given' do
274
- context 'when x509_encryption_url is given' do
275
- let(:x509_encryption_url) { 'http://provider.example.com/x509_encryption.pem' }
276
- its(:signing_key) { should be_nil }
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) { "https://connect-op.heroku.com/.well-known/openid-configuration" }
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.user_info_endpoint.should == 'https://connect-op.heroku.com/user_info'
17
- config.refresh_session_endpoint.should be_nil
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.jwk_url.should be_nil
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 == ["openid", "profile", "email", "address"]
23
- config.response_types_supported.should == ["code", "token", "id_token", "code token", "code id_token", "id_token token"]
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 == ["public", "pairwise"]
26
- config.claims_supported.should == ["sub", "iss", "name", "email"]
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) { "https://connect-op.heroku.com:8080/.well-known/openid-configuration" }
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) { "https://connect.openid4.us/abop/.well-known/openid-configuration" }
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.user_info.required?(:name).should be_true
97
- request_object.user_info.optional?(:name).should be_false
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.user_info.required?(:email).should be_false
104
- request_object.user_info.optional?(:email).should be_true
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