openid_connect 0.6.1 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +5 -5
  2. data/.github/FUNDING.yml +3 -0
  3. data/.github/workflows/spec.yml +31 -0
  4. data/.gitignore +1 -0
  5. data/CHANGELOG.md +23 -0
  6. data/LICENSE +3 -1
  7. data/README.rdoc +10 -3
  8. data/Rakefile +6 -6
  9. data/TODOs +12 -0
  10. data/VERSION +1 -1
  11. data/lib/openid_connect/access_token/mtls.rb +9 -0
  12. data/lib/openid_connect/access_token.rb +14 -6
  13. data/lib/openid_connect/client/registrar.rb +69 -130
  14. data/lib/openid_connect/client.rb +7 -12
  15. data/lib/openid_connect/discovery/provider/config/resource.rb +5 -3
  16. data/lib/openid_connect/discovery/provider/config/response.rb +73 -78
  17. data/lib/openid_connect/discovery/provider/config.rb +5 -2
  18. data/lib/openid_connect/discovery/provider.rb +6 -2
  19. data/lib/openid_connect/discovery.rb +0 -2
  20. data/lib/openid_connect/jwtnizable.rb +6 -4
  21. data/lib/openid_connect/request_object/claimable.rb +4 -6
  22. data/lib/openid_connect/request_object.rb +6 -13
  23. data/lib/openid_connect/response_object/id_token.rb +38 -37
  24. data/lib/openid_connect/response_object/user_info/address.rb +10 -0
  25. data/lib/openid_connect/response_object/user_info.rb +64 -2
  26. data/lib/openid_connect.rb +26 -11
  27. data/lib/rack/oauth2/server/authorize/extension/code_and_id_token.rb +5 -1
  28. data/lib/rack/oauth2/server/authorize/extension/code_and_id_token_and_token.rb +1 -1
  29. data/lib/rack/oauth2/server/authorize/extension/id_token.rb +1 -1
  30. data/lib/rack/oauth2/server/authorize/extension/id_token_and_token.rb +1 -1
  31. data/lib/rack/oauth2/server/authorize/request_with_connect_params.rb +17 -14
  32. data/lib/rack/oauth2/server/id_token_response.rb +11 -13
  33. data/openid_connect.gemspec +19 -13
  34. data/spec/helpers/crypto_spec_helper.rb +2 -2
  35. data/spec/helpers/webmock_helper.rb +14 -9
  36. data/spec/mock_response/access_token/without_token_type.json +3 -0
  37. data/spec/mock_response/discovery/config.json +3 -3
  38. data/spec/mock_response/discovery/config_with_custom_port.json +13 -0
  39. data/spec/mock_response/discovery/config_with_invalid_issuer.json +13 -0
  40. data/spec/mock_response/discovery/config_with_path.json +13 -0
  41. data/spec/mock_response/discovery/config_without_issuer.json +12 -0
  42. data/spec/mock_response/errors/unknown.json +3 -1
  43. data/spec/mock_response/public_keys/{jwk.json → jwks.json} +1 -1
  44. data/spec/mock_response/public_keys/jwks_with_private_key.json +8 -0
  45. data/spec/mock_response/public_keys/private_key.pem +27 -0
  46. data/spec/openid_connect/access_token_spec.rb +11 -20
  47. data/spec/openid_connect/client/registrar_spec.rb +93 -208
  48. data/spec/openid_connect/client_spec.rb +79 -22
  49. data/spec/openid_connect/connect_object_spec.rb +1 -1
  50. data/spec/openid_connect/discovery/provider/config/response_spec.rb +76 -284
  51. data/spec/openid_connect/discovery/provider/config_spec.rb +64 -27
  52. data/spec/openid_connect/discovery/provider_spec.rb +2 -2
  53. data/spec/openid_connect/request_object_spec.rb +4 -4
  54. data/spec/openid_connect/response_object/id_token_spec.rb +94 -52
  55. data/spec/openid_connect/response_object/user_info/{open_id/address_spec.rb → address_spec.rb} +3 -3
  56. data/spec/openid_connect/response_object/{user_info/open_id_spec.rb → user_info_spec.rb} +13 -12
  57. data/spec/openid_connect_spec.rb +19 -19
  58. data/spec/rack/oauth2/server/authorize/extension/code_and_id_token_and_token_spec.rb +11 -0
  59. data/spec/rack/oauth2/server/authorize/extension/code_and_id_token_spec.rb +11 -0
  60. data/spec/rack/oauth2/server/authorize/extension/id_token_and_token_spec.rb +11 -0
  61. data/spec/rack/oauth2/server/authorize/extension/id_token_spec.rb +1 -1
  62. data/spec/rack/oauth2/server/authorize/request_with_connect_params_spec.rb +45 -0
  63. data/spec/spec_helper.rb +12 -1
  64. metadata +155 -90
  65. data/.travis.yml +0 -3
  66. data/Gemfile.lock +0 -102
  67. data/lib/openid_connect/debugger/request_filter.rb +0 -28
  68. data/lib/openid_connect/debugger.rb +0 -3
  69. data/lib/openid_connect/response_object/user_info/open_id/address.rb +0 -12
  70. data/lib/openid_connect/response_object/user_info/open_id.rb +0 -64
  71. data/lib/rack/oauth2/server/resource/error_with_connect_ext.rb +0 -14
  72. data/spec/mock_response/public_keys/x509.pem +0 -21
  73. data/spec/openid_connect/debugger/request_filter_spec.rb +0 -33
  74. data/spec/rack/oauth2/server/resource/error_with_connect_ext_spec.rb +0 -12
  75. /data/spec/mock_response/{user_info → userinfo}/openid.json +0 -0
@@ -19,7 +19,20 @@ describe OpenIDConnect::ResponseObject::IdToken do
19
19
  describe 'attributes' do
20
20
  subject { klass }
21
21
  its(:required_attributes) { should == [:iss, :sub, :aud, :exp, :iat] }
22
- its(:optional_attributes) { should == [:acr, :auth_time, :nonce, :sub_jwk, :at_hash, :c_hash] }
22
+ its(:optional_attributes) { should == [:acr, :amr, :azp, :jti, :sid, :auth_time, :nonce, :sub_jwk, :at_hash, :c_hash, :s_hash] }
23
+
24
+ describe 'auth_time' do
25
+ subject { id_token.auth_time }
26
+
27
+ context 'when Time object given' do
28
+ let(:attributes) do
29
+ required_attributes.merge(auth_time: Time.now)
30
+ end
31
+ it do
32
+ should be_a Numeric
33
+ end
34
+ end
35
+ end
23
36
  end
24
37
 
25
38
  describe '#verify!' do
@@ -28,7 +41,18 @@ describe OpenIDConnect::ResponseObject::IdToken do
28
41
  id_token.verify!(
29
42
  issuer: attributes[:iss],
30
43
  client_id: attributes[:aud]
31
- ).should be_true
44
+ ).should == true
45
+ end
46
+
47
+ context 'when aud(ience) is an array of identifiers' do
48
+ let(:client_id) { 'client_id' }
49
+ let(:attributes) { required_attributes.merge(aud: ['some_other_identifier', client_id]) }
50
+ it do
51
+ id_token.verify!(
52
+ issuer: attributes[:iss],
53
+ client_id: client_id
54
+ ).should == true
55
+ end
32
56
  end
33
57
 
34
58
  context 'when expired' do
@@ -95,7 +119,7 @@ describe OpenIDConnect::ResponseObject::IdToken do
95
119
  issuer: attributes[:iss],
96
120
  client_id: attributes[:aud],
97
121
  nonce: attributes[:nonce]
98
- ).should be_true
122
+ ).should == true
99
123
  end
100
124
  end
101
125
 
@@ -133,7 +157,7 @@ describe OpenIDConnect::ResponseObject::IdToken do
133
157
  t = id_token.to_jwt private_key do |t|
134
158
  t.header[:x5u] = "http://server.example.com/x5u"
135
159
  end
136
- h = UrlSafeBase64.decode64 t.split('.').first
160
+ h = Base64.urlsafe_decode64 t.split('.').first
137
161
  h.should include 'x5u'
138
162
  end
139
163
  end
@@ -145,8 +169,9 @@ describe OpenIDConnect::ResponseObject::IdToken do
145
169
  jwt = JSON::JWT.decode t, public_key
146
170
  jwt.should include :at_hash
147
171
  jwt.should_not include :c_hash
148
- jwt[:at_hash].should == UrlSafeBase64.encode64(
149
- OpenSSL::Digest::SHA256.digest('access_token')[0, 128 / 8]
172
+ jwt[:at_hash].should == Base64.urlsafe_encode64(
173
+ OpenSSL::Digest::SHA256.digest('access_token')[0, 128 / 8],
174
+ padding: false
150
175
  )
151
176
  end
152
177
  end
@@ -169,8 +194,9 @@ describe OpenIDConnect::ResponseObject::IdToken do
169
194
  jwt = JSON::JWT.decode t, public_key
170
195
  jwt.should_not include :at_hash
171
196
  jwt.should include :c_hash
172
- jwt[:c_hash].should == UrlSafeBase64.encode64(
173
- OpenSSL::Digest::SHA256.digest('authorization_code')[0, 128 / 8]
197
+ jwt[:c_hash].should == Base64.urlsafe_encode64(
198
+ OpenSSL::Digest::SHA256.digest('authorization_code')[0, 128 / 8],
199
+ padding: false
174
200
  )
175
201
  end
176
202
  end
@@ -185,11 +211,13 @@ describe OpenIDConnect::ResponseObject::IdToken do
185
211
  jwt = JSON::JWT.decode t, public_key
186
212
  jwt.should include :at_hash
187
213
  jwt.should include :c_hash
188
- jwt[:at_hash].should == UrlSafeBase64.encode64(
189
- OpenSSL::Digest::SHA256.digest('access_token')[0, 128 / 8]
214
+ jwt[:at_hash].should == Base64.urlsafe_encode64(
215
+ OpenSSL::Digest::SHA256.digest('access_token')[0, 128 / 8],
216
+ padding: false
190
217
  )
191
- jwt[:c_hash].should == UrlSafeBase64.encode64(
192
- OpenSSL::Digest::SHA256.digest('authorization_code')[0, 128 / 8]
218
+ jwt[:c_hash].should == Base64.urlsafe_encode64(
219
+ OpenSSL::Digest::SHA256.digest('authorization_code')[0, 128 / 8],
220
+ padding: false
193
221
  )
194
222
  end
195
223
  end
@@ -221,11 +249,60 @@ describe OpenIDConnect::ResponseObject::IdToken do
221
249
  its(key) { should == attributes[key] }
222
250
  end
223
251
  its(:exp) { should == attributes[:exp].to_i }
252
+ its(:raw_attributes) { should be_instance_of JSON::JWS }
253
+
254
+ context 'when IdP config is given' do
255
+ subject { klass.decode id_token.to_jwt(private_key), idp_config }
256
+ let(:jwks) do
257
+ jwk_str = File.read(File.join(__dir__, '../../mock_response/public_keys/jwks_with_private_key.json'))
258
+ jwk = JSON::JWK::Set.new JSON.parse(jwk_str)
259
+ end
260
+ let(:idp_config) do
261
+ OpenIDConnect::Discovery::Provider::Config::Response.new(
262
+ issuer: attributes[:issuer],
263
+ authorization_endpoint: File.join(attributes[:iss], 'authorize'),
264
+ jwks_uri: File.join(attributes[:iss], 'jwks'),
265
+ response_types_supported: ['code'],
266
+ subject_types_supported: ['public'],
267
+ id_token_signing_alg_values_supported: ['RS256']
268
+ )
269
+ end
270
+
271
+ context 'when id_token has kid' do
272
+ let(:private_key) do
273
+ OpenSSL::PKey::RSA.new(
274
+ File.read(File.join(__dir__, '../../mock_response/public_keys/private_key.pem'))
275
+ ).to_jwk
276
+ end
277
+
278
+ it do
279
+ mock_json :get, idp_config.jwks_uri, 'public_keys/jwks_with_private_key' do
280
+ should be_a klass
281
+ end
282
+ end
283
+ end
284
+
285
+ context 'otherwise' do
286
+ let(:private_key) do
287
+ OpenSSL::PKey::RSA.new(
288
+ File.read(File.join(__dir__, '../../mock_response/public_keys/private_key.pem'))
289
+ )
290
+ end
291
+
292
+ it do
293
+ mock_json :get, idp_config.jwks_uri, 'public_keys/jwks_with_private_key' do
294
+ expect do
295
+ should
296
+ end.to raise_error JSON::JWK::Set::KidNotFound
297
+ end
298
+ end
299
+ end
300
+ end
224
301
 
225
302
  context 'when self-issued' do
226
303
  context 'when valid' do
227
304
  let(:self_issued) do
228
- 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL3NlbGYtaXNzdWVkLm1lIiwic3ViIjoiUFdFYXFfVnlUd1hTSFR4QVlSZHdWTjNMN2s0UnNxOVBwaTZ4WHZ6ZGZWTSIsImF1ZCI6InRhcGlkLnRhcGlkZW50aXR5LmNvbSIsImV4cCI6MTM2MjI3OTkwMCwiaWF0IjoxMzYyMjc2MzAwLCJzdWJfandrIjp7ImFsZyI6IlJTQSIsIm4iOiJ5R21SUm5qSkk2VWhXYUtYcUJxa0RodDVQa0FPdDNqV2Y0SUxIdUlKZHJHR3h1ajBhcDIzLXlxaS16N29jZmF3dnlNbkRfakRpY0JjRTFtVHduZ2ZLRURMdmp5ZWw4U3VhZlZJWTR4ZDVDcG42Nlp4U2pocE1yTWZtMF9palZtdkQ0OTZHZzZSYUR4cHA4OEVqcUlaZUtyZEtqd2lOeTRGZ0dkVnZPQURXWG85R0xLenBOdlc2MGU3MkdrRGFkUVJncEhGNjNVaE9zaVltYmwxRVRMaVhLMGpUdldDdEZVdUlfT2lTN3hIUmU0X3FSaWxRc240cGlHTy1lNzJ2azRpaFlPaldoRXNpcnU2X0JtSC03YWs2Qk9lY3pUYTFVOFZyQzY1ZkRabzRxeG9uRWVoeVpVVnItSmxXMFVvbFVTS1dKOE1OMGRBV1VaeTFBZUxtRzliZlEiLCJlIjoiQVFBQiJ9fQ.obpb9tshLoZG6O32w4nB4I3nBtR_2mscVeNuPWZAGIwq9SqpiNF24KrGrhgbJMzRndafXbOdiiTFjq15BDwoSUrRF2H2EQXm1_lZxhw66JK4get7zEihtmsljGxB03LRlej-ec6baAKJxCBZdJ7SIantjgyt_WbAY27ImeryD7Wi9VKtgEzX2cFbU8u5VwxpisDfosp7fpp0_jdAdk948eJnercM-6t0a3UhLoLaW1RWZSbzXzef9aDuMezsnSrwafjYuF6dzUF7uAEdsYAzMeISch2_Gl4Twbrovmmqj50IKIctkLxQBTI1_v0oU63_a4jLami1cux8XTEfgPEPmg'
305
+ 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL3NlbGYtaXNzdWVkLm1lIiwic3ViIjoiMmdDUWFLUmJkY0RaeUlDTE92ODJJR2EtdHBSVU52QW1ZN3BnZ3Z5NGdENCIsImF1ZCI6ImNsaWVudC5leGFtcGxlLmNvbSIsImV4cCI6MTQ0MjQ4Mjc4MiwiaWF0IjoxNDQxODc3OTgyLCJzdWJfandrIjp7Imt0eSI6IlJTQSIsImUiOiJBUUFCIiwibiI6IjN1RzNiSTV6MTFhM1hlOXUyZFVJNDBpcWZrVl9vTmFQVmNlalN4V3l0YnMybTZKMGMzNjJESlJQNGtyUl9TZjNtQXJ3Qjd6Qm5UWExkbW1tZW85VzloSDhsSnFGOUthMTY3dHBTQWJCajB1MjhyaTgwZFZ4NUxzblJTX19uUUd6Y3dNa2sxTTBERUx2X0FXbVYwU2JudDhJZEpSeFhwdG5xRE5tWXJ0cmItMkk0a1lwRHlwN2pvTXd0bDNXeGp2cnkwbENLNExqOU9SeXdod05zYUU2MHFsako5aHBGZV8wTmpmaThzaVBlMDRJSkFaUjl3NXo0TnAtQS1HbWdmeTNJTmNZVFYyQ25FekNSY29HSGl5OGduRzA1a015TnRtZTFVdV8xanBhdF9lcF9QUG9PWEJ6Q1NwbzB5QlRNSWhmdEJTQ3p2a2V1ZFdhNks2aW5LMkYxdyJ9fQ.wchF80oFxdjEcOEwPZ9TUlV6R96Vz8XK9MzednMOsZmEMnNSEqKKTyO0Mhp9lijJPZX8J7lTtAGkz4gfsjyoYBIHQOTf0qHRHSx9RTeC31whw1TJ9x5V6UXpKN0EW1EhjAEGIZ0EyFJ-cRTgVs0V7PT7e63JOUYyW6LqqHa4MV9SdK8BdnaN0D4-402Pf7yFqjneSHq3KZbXcgjUPT_hszsGvnn9qEyuIHQqON6YnDt55z5SvP_RfKtBfUe2VY-yglJT41LfhkIgpvjLYdYYRPh9G9ftJr17qht5RtHSNpTp4FPw7BR7rCnptb4xTxyq-sLu7qjSLRtqQ35Xpi_6qQ'
229
306
  end
230
307
 
231
308
  context 'when key == :self_issued' do
@@ -247,7 +324,7 @@ describe OpenIDConnect::ResponseObject::IdToken do
247
324
 
248
325
  context 'when invalid subject' do
249
326
  let(:self_issued) do
250
- 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJkZXZpY2VfdG9rZW4iOiI2NjYxNmI2NTJkNjQ2NTc2Njk2MzY1MmQ3NDZmNmI2NTZlIiwiaXNzIjoiaHR0cHM6Ly9zZWxmLWlzc3VlZC5tZSIsInN1YiI6IlBXRWFxX1Z5VHdYU0hUeEFZUmR3Vk4zTDdrNFJzcTlQcGk2eFh2emRmVk1pbnZhbGlkIiwiYXVkIjoidGFwaWQudGFwaWRlbnRpdHkuY29tIiwiZXhwIjoxMzYyMjgwMDQxLCJpYXQiOjEzNjIyNzY0NDEsInN1Yl9qd2siOnsiYWxnIjoiUlNBIiwibiI6InlHbVJSbmpKSTZVaFdhS1hxQnFrRGh0NVBrQU90M2pXZjRJTEh1SUpkckdHeHVqMGFwMjMteXFpLXo3b2NmYXd2eU1uRF9qRGljQmNFMW1Ud25nZktFREx2anllbDhTdWFmVklZNHhkNUNwbjY2WnhTamhwTXJNZm0wX2lqVm12RDQ5NkdnNlJhRHhwcDg4RWpxSVplS3JkS2p3aU55NEZnR2RWdk9BRFdYbzlHTEt6cE52VzYwZTcyR2tEYWRRUmdwSEY2M1VoT3NpWW1ibDFFVExpWEswalR2V0N0RlV1SV9PaVM3eEhSZTRfcVJpbFFzbjRwaUdPLWU3MnZrNGloWU9qV2hFc2lydTZfQm1ILTdhazZCT2VjelRhMVU4VnJDNjVmRFpvNHF4b25FZWh5WlVWci1KbFcwVW9sVVNLV0o4TU4wZEFXVVp5MUFlTG1HOWJmUSIsImUiOiJBUUFCIn19.K8NpQ1r89v9KFcrAU19-qTEtUv94gTJp25xwYwKPttkMOduGMIBn1lCTUsWhUC8NDc0lJrIq-MAa3Eav6wlW9HkX4Gw7vD-fwx6bijm_0LnxLcK2PwMPeeAaeztEOj6WNnUlipZAkOjYhFWG_4gK4sbnoXv80LSV3dHf0mwDEp0vWJ5rba24YfyFb_CoGfeluaHVQiCWTNFa4rh5ohCb1oC4IAZd607KNryLBbjGdyRgIgeIBtph_rx4Jf2tYhBs1_Y32KQMgKHy7QBJHD1hr2HEAu_pCXirwpNFcBCV7K5vUYntYSjdrKfvEzeW0Jxjm1AGgMZr_NsGwNS0bMYoUA'
327
+ 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL3NlbGYtaXNzdWVkLm1lIiwic3ViIjoiUFdFYXFfVnlUd1hTSFR4QVlSZHdWTjNMN2s0UnNxOVBwaTZ4WHZ6ZGZWTSIsImF1ZCI6InRhcGlkLnRhcGlkZW50aXR5LmNvbSIsImV4cCI6MTM2MjI3OTkwMCwiaWF0IjoxMzYyMjc2MzAwLCJzdWJfandrIjp7Imt0eSI6IlJTQSIsImUiOiJBUUFCIiwibiI6IjRGTWl5M08zbFlOd2RzeC15aXVjemRsek81eU11d1p4WFlzSDgydmM0RkM0QXgyMGpNVV94emJHSUhWVUtFQ0pndFp3clBlajhRSWUtZFZFYXQtaGxjNTB5TXluM0h3cmtJVjVZOTdET1E2Sks4azk2QTFqVWxPLW5sRjl4ZUx2VDlwYTJXRTZtYm1KOG5EQW5mR0d6bmRNd3VKNzVLZDI2YmZHY21wcm5qUUJLTkVrakdJbW9MMEhFODFUcjROeC1tN1lsYkRGaVFNRDVpYjhCY3N4S0tvMTZTeG5tSi1EeUY2c094Y2JtV1ZrdkZBa3FKWFBnVFVoNXVYT3YwYk9nN0I2d2RHdUMtWnpJUl8tdUx3YlcxN2V4NGx3ZTFPb0ppdFJ3SFczYlo3NEc3RkdoSmhfTUp4YzB3WXBkbW5uNVpjRFFOWl9sWVRvMHYzaU1PUWk3USJ9fQ.DZKaSne22DjKFSpSUphsTeCMkcMWDexQCm8BPb1nI1PzQYsEAOfwumDajt85UA0x28y2zuOevMj29VpwTzbpRDkduv2NWAI4MHw8DYEsIN__-QGANmdU1sKmthET2iFmeFySwWomLqFvYIaNmVYVLkD53Zqfct5qH3Wznd_hrK8T1d6Cxg-gyZlAeqEu2V8EL2yuz8Gdaeze4b78l5Ux-B_5FQhZ3UkXbL1B2gzKJQVKAQdFJb9zUfzmCeIiUmeM9mw_VU64tAvFDRiTKS1P6b62Gxuyx1DhMLFg2evDaTJERJOta9ywtPfdcLH3qcIiUBffP2-FnAz44bOlKzJorQ'
251
328
  end
252
329
 
253
330
  it do
@@ -286,43 +363,8 @@ describe OpenIDConnect::ResponseObject::IdToken do
286
363
  [:iss, :sub, :aud, :exp, :iat, :sub_jwk].each do |attribute|
287
364
  its(attribute) { should be_present }
288
365
  end
289
- its(:iss) { should == 'https://self-issued.me' }
366
+ its(:iss) { should == 'https://self-issued.me' }
290
367
  its(:sub_jwk) { should == sub_jwk}
291
- its(:subject) { should == OpenIDConnect::ResponseObject::IdToken.self_issued_subject(sub_jwk) }
292
- end
293
-
294
- describe '.self_issued_subject' do
295
- context 'when RSA key given' do
296
- let(:jwk) { JSON::JWK.new(public_key) }
297
- it do
298
- user_id = klass.self_issued_subject jwk
299
- user_id.should == UrlSafeBase64.encode64(
300
- OpenSSL::Digest::SHA256.digest([jwk[:n], jwk[:e]].join)
301
- )
302
- end
303
- end
304
-
305
- context 'when EC key given' do
306
- let(:jwk) { JSON::JWK.new(ec_public_key) }
307
- it do
308
- expect do
309
- klass.self_issued_subject jwk
310
- end.to raise_error NotImplementedError
311
- end
312
- end
313
-
314
- context 'when unknown algorithm JWK given' do
315
- let(:jwk) do
316
- {
317
- alg: 'unknown'
318
- }
319
- end
320
-
321
- it do
322
- expect do
323
- klass.self_issued_subject jwk
324
- end.to raise_error OpenIDConnect::ResponseObject::IdToken::InvalidToken
325
- end
326
- end
368
+ its(:subject) { should == sub_jwk.thumbprint }
327
369
  end
328
- end
370
+ end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe OpenIDConnect::ResponseObject::UserInfo::OpenID::Address do
4
- let(:klass) { OpenIDConnect::ResponseObject::UserInfo::OpenID::Address }
3
+ describe OpenIDConnect::ResponseObject::UserInfo::Address do
4
+ let(:klass) { OpenIDConnect::ResponseObject::UserInfo::Address }
5
5
 
6
6
  describe 'attributes' do
7
7
  subject { klass }
@@ -20,7 +20,7 @@ describe OpenIDConnect::ResponseObject::UserInfo::OpenID::Address do
20
20
  let :attributes do
21
21
  {}
22
22
  end
23
- its(:valid?) { should be_false }
23
+ its(:valid?) { should == false }
24
24
  its(:errors) { should include :base }
25
25
  end
26
26
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe OpenIDConnect::ResponseObject::UserInfo::OpenID do
4
- let(:klass) { OpenIDConnect::ResponseObject::UserInfo::OpenID }
3
+ describe OpenIDConnect::ResponseObject::UserInfo do
4
+ let(:klass) { OpenIDConnect::ResponseObject::UserInfo }
5
5
  let(:instance) { klass.new attributes }
6
6
  subject { instance }
7
7
 
@@ -27,8 +27,9 @@ describe OpenIDConnect::ResponseObject::UserInfo::OpenID do
27
27
  :zoneinfo,
28
28
  :locale,
29
29
  :phone_number,
30
+ :phone_number_verified,
30
31
  :address,
31
- :updated_time
32
+ :updated_at
32
33
  ]
33
34
  end
34
35
  end
@@ -44,7 +45,7 @@ describe OpenIDConnect::ResponseObject::UserInfo::OpenID do
44
45
  let :attributes do
45
46
  {}
46
47
  end
47
- its(:valid?) { should be_false }
48
+ its(:valid?) { should == false }
48
49
  its(:errors) { should include :base }
49
50
  end
50
51
 
@@ -52,16 +53,16 @@ describe OpenIDConnect::ResponseObject::UserInfo::OpenID do
52
53
  let :attributes do
53
54
  {email: 'nov@localhost'}
54
55
  end
55
- its(:valid?) { should be_false }
56
+ its(:valid?) { should == false }
56
57
  its(:errors) { should include :email }
57
58
  end
58
59
 
59
- [:email_verified, :gender, :zoneinfo].each do |one_of_list|
60
+ [:email_verified, :zoneinfo].each do |one_of_list|
60
61
  context "when #{one_of_list} is invalid" do
61
62
  let :attributes do
62
63
  {one_of_list => 'Out of List'}
63
64
  end
64
- its(:valid?) { should be_false }
65
+ its(:valid?) { should == false }
65
66
  its(:errors) { should include one_of_list }
66
67
  end
67
68
  end
@@ -75,7 +76,7 @@ describe OpenIDConnect::ResponseObject::UserInfo::OpenID do
75
76
  let :attributes do
76
77
  {url => 'Invalid'}
77
78
  end
78
- its(:valid?) { should be_false }
79
+ its(:valid?) { should == false }
79
80
  its(:errors) { should include url }
80
81
  end
81
82
  end
@@ -84,7 +85,7 @@ describe OpenIDConnect::ResponseObject::UserInfo::OpenID do
84
85
  let :attributes do
85
86
  {address: {}}
86
87
  end
87
- its(:valid?) { should be_false }
88
+ its(:valid?) { should == false }
88
89
  its(:errors) { should include :address }
89
90
  end
90
91
  end
@@ -94,14 +95,14 @@ describe OpenIDConnect::ResponseObject::UserInfo::OpenID do
94
95
  let :attributes do
95
96
  {address: {}}
96
97
  end
97
- its(:address) { should be_a OpenIDConnect::ResponseObject::UserInfo::OpenID::Address }
98
+ its(:address) { should be_a OpenIDConnect::ResponseObject::UserInfo::Address }
98
99
  end
99
100
 
100
101
  context 'when Address is given' do
101
102
  let :attributes do
102
- {address: OpenIDConnect::ResponseObject::UserInfo::OpenID::Address.new}
103
+ {address: OpenIDConnect::ResponseObject::UserInfo::Address.new}
103
104
  end
104
- its(:address) { should be_a OpenIDConnect::ResponseObject::UserInfo::OpenID::Address }
105
+ its(:address) { should be_a OpenIDConnect::ResponseObject::UserInfo::Address }
105
106
  end
106
107
  end
107
108
 
@@ -4,24 +4,24 @@ describe OpenIDConnect do
4
4
  after { OpenIDConnect.debugging = false }
5
5
 
6
6
  its(:logger) { should be_a Logger }
7
- its(:debugging?) { should be_false }
7
+ its(:debugging?) { should == false }
8
8
 
9
9
  describe '.debug!' do
10
10
  before { OpenIDConnect.debug! }
11
- its(:debugging?) { should be_true }
11
+ its(:debugging?) { should == true }
12
12
  end
13
13
 
14
14
  describe '.debug' do
15
15
  it 'should enable debugging within given block' do
16
16
  OpenIDConnect.debug do
17
- SWD.debugging?.should be_true
18
- WebFinger.debugging?.should be_true
19
- Rack::OAuth2.debugging?.should be_true
20
- OpenIDConnect.debugging?.should be_true
17
+ SWD.debugging?.should == true
18
+ WebFinger.debugging?.should == true
19
+ Rack::OAuth2.debugging?.should == true
20
+ OpenIDConnect.debugging?.should == true
21
21
  end
22
- SWD.debugging?.should be_false
23
- Rack::OAuth2.debugging?.should be_false
24
- OpenIDConnect.debugging?.should be_false
22
+ SWD.debugging?.should == false
23
+ Rack::OAuth2.debugging?.should == false
24
+ OpenIDConnect.debugging?.should == false
25
25
  end
26
26
 
27
27
  it 'should not force disable debugging' do
@@ -30,15 +30,15 @@ describe OpenIDConnect do
30
30
  Rack::OAuth2.debug!
31
31
  OpenIDConnect.debug!
32
32
  OpenIDConnect.debug do
33
- SWD.debugging?.should be_true
34
- WebFinger.debugging?.should be_true
35
- Rack::OAuth2.debugging?.should be_true
36
- OpenIDConnect.debugging?.should be_true
33
+ SWD.debugging?.should == true
34
+ WebFinger.debugging?.should == true
35
+ Rack::OAuth2.debugging?.should == true
36
+ OpenIDConnect.debugging?.should == true
37
37
  end
38
- SWD.debugging?.should be_true
39
- WebFinger.debugging?.should be_true
40
- Rack::OAuth2.debugging?.should be_true
41
- OpenIDConnect.debugging?.should be_true
38
+ SWD.debugging?.should == true
39
+ WebFinger.debugging?.should == true
40
+ Rack::OAuth2.debugging?.should == true
41
+ OpenIDConnect.debugging?.should == true
42
42
  end
43
43
  end
44
44
 
@@ -46,12 +46,12 @@ describe OpenIDConnect do
46
46
  context 'with http_config' do
47
47
  before do
48
48
  OpenIDConnect.http_config do |config|
49
- config.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
49
+ config.ssl.verify = false
50
50
  end
51
51
  end
52
52
  it 'should configure OpenIDConnect, SWD and Rack::OAuth2\'s http_client' do
53
53
  [OpenIDConnect, SWD, WebFinger, Rack::OAuth2].each do |klass|
54
- klass.http_client.ssl_config.verify_mode.should == OpenSSL::SSL::VERIFY_NONE
54
+ klass.http_client.ssl.verify.should be_falsy
55
55
  end
56
56
  end
57
57
  end
@@ -53,4 +53,15 @@ describe Rack::OAuth2::Server::Authorize::Extension::CodeAndIdTokenAndToken do
53
53
  expect { response }.to raise_error AttrRequired::AttrMissing, "'access_token', 'code', 'id_token' required."
54
54
  end
55
55
  end
56
+
57
+ context 'when error response' do
58
+ let(:env) { Rack::MockRequest.env_for("/authorize?client_id=client_id") }
59
+ let(:request) { Rack::OAuth2::Server::Authorize::Extension::CodeAndIdTokenAndToken::Request.new env }
60
+
61
+ it 'should set protocol_params_location = :fragment' do
62
+ expect { request.bad_request! }.to raise_error(Rack::OAuth2::Server::Authorize::BadRequest) { |e|
63
+ e.protocol_params_location.should == :fragment
64
+ }
65
+ end
66
+ end
56
67
  end
@@ -50,4 +50,15 @@ describe Rack::OAuth2::Server::Authorize::Extension::CodeAndIdToken do
50
50
  expect { response }.to raise_error AttrRequired::AttrMissing, "'id_token' required."
51
51
  end
52
52
  end
53
+
54
+ context 'when error response' do
55
+ let(:env) { Rack::MockRequest.env_for("/authorize?client_id=client_id") }
56
+ let(:request) { Rack::OAuth2::Server::Authorize::Extension::CodeAndIdToken::Request.new env }
57
+
58
+ it 'should set protocol_params_location = :fragment' do
59
+ expect { request.bad_request! }.to raise_error(Rack::OAuth2::Server::Authorize::BadRequest) { |e|
60
+ e.protocol_params_location.should == :fragment
61
+ }
62
+ end
63
+ end
53
64
  end
@@ -51,4 +51,15 @@ describe Rack::OAuth2::Server::Authorize::Extension::IdTokenAndToken do
51
51
  expect { response }.to raise_error AttrRequired::AttrMissing, "'id_token' required."
52
52
  end
53
53
  end
54
+
55
+ context 'when error response' do
56
+ let(:env) { Rack::MockRequest.env_for("/authorize?client_id=client_id") }
57
+ let(:request) { Rack::OAuth2::Server::Authorize::Extension::IdTokenAndToken::Request.new env }
58
+
59
+ it 'should set protocol_params_location = :fragment' do
60
+ expect { request.bad_request! }.to raise_error(Rack::OAuth2::Server::Authorize::BadRequest) { |e|
61
+ e.protocol_params_location.should == :fragment
62
+ }
63
+ end
64
+ end
54
65
  end
@@ -62,7 +62,7 @@ describe Rack::OAuth2::Server::Authorize::Extension::IdToken do
62
62
  let(:env) { Rack::MockRequest.env_for("/authorize?client_id=client_id&scope=openid") }
63
63
  let(:request) { Rack::OAuth2::Server::Authorize::Extension::IdToken::Request.new env }
64
64
  it do
65
- request.openid_connect_request?.should be_true
65
+ request.openid_connect_request?.should == true
66
66
  end
67
67
  end
68
68
  end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rack::OAuth2::Server::Authorize::RequestWithConnectParams do
4
+ let(:base_params) do
5
+ {
6
+ client_id: 'client_id',
7
+ redirect_uri: 'https://client.example.com/callback'
8
+ }
9
+ end
10
+ let(:env) { Rack::MockRequest.env_for("/authorize?#{base_params.to_query}&#{params.to_query}") }
11
+ let(:request) { Rack::OAuth2::Server::Authorize::Request.new env }
12
+ subject { request }
13
+
14
+ describe 'prompt' do
15
+ context 'when a space-delimited string given' do
16
+ let(:params) do
17
+ {prompt: 'login consent'}
18
+ end
19
+ its(:prompt) { should == ['login', 'consent']}
20
+ end
21
+
22
+ context 'when a single string given' do
23
+ let(:params) do
24
+ {prompt: 'login'}
25
+ end
26
+ its(:prompt) { should == ['login']}
27
+ end
28
+ end
29
+
30
+ describe 'max_age' do
31
+ context 'when numeric value given' do
32
+ let(:params) do
33
+ {max_age: '5'}
34
+ end
35
+ its(:max_age) { should == 5}
36
+ end
37
+
38
+ context 'when non-numeric string given' do
39
+ let(:params) do
40
+ {max_age: 'foo'}
41
+ end
42
+ its(:max_age) { should == 0}
43
+ end
44
+ end
45
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,18 @@
1
- require 'cover_me'
1
+ require 'simplecov'
2
+
3
+ SimpleCov.start do
4
+ add_filter 'spec'
5
+ end
2
6
 
3
7
  require 'rspec'
8
+ require 'rspec/its'
4
9
  require 'openid_connect'
5
10
 
11
+ RSpec.configure do |config|
12
+ config.expect_with :rspec do |c|
13
+ c.syntax = [:should, :expect]
14
+ end
15
+ end
16
+
6
17
  require 'helpers/crypto_spec_helper'
7
18
  require 'helpers/webmock_helper'