openid_connect 0.6.1 → 2.3.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.
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'