openid_connect 0.3.6 → 0.3.7

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.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- openid_connect (0.3.6)
4
+ openid_connect (0.3.7)
5
5
  activemodel (>= 3)
6
6
  attr_required (>= 0.0.5)
7
7
  json (>= 1.4.3)
@@ -35,6 +35,7 @@ GEM
35
35
  httpclient (2.3.0.1)
36
36
  i18n (0.6.1)
37
37
  json (1.7.5)
38
+ json (1.7.5-java)
38
39
  json-jwt (0.3.3)
39
40
  activesupport (>= 2.3)
40
41
  i18n
@@ -73,7 +74,7 @@ GEM
73
74
  treetop (1.4.11)
74
75
  polyglot
75
76
  polyglot (>= 0.3.1)
76
- tzinfo (0.3.33)
77
+ tzinfo (0.3.34)
77
78
  url_safe_base64 (0.2.1)
78
79
  validate_email (0.1.6)
79
80
  activemodel (>= 3.0)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.6
1
+ 0.3.7
@@ -28,11 +28,11 @@ module OpenIDConnect
28
28
  include JWTnizable
29
29
 
30
30
  class << self
31
- def decode(jwt_string, key)
31
+ def decode(jwt_string, key = nil)
32
32
  new JSON::JWT.decode(jwt_string, key)
33
33
  end
34
34
 
35
- def fetch(request_uri, key)
35
+ def fetch(request_uri, key = nil)
36
36
  jwt_string = OpenIDConnect.http_client.get_content(request_uri)
37
37
  decode jwt_string, key
38
38
  end
@@ -63,20 +63,32 @@ module OpenIDConnect
63
63
  jwt = JSON::JWT.decode jwt_string, :skip_verification
64
64
  jwk = jwt[:user_jwk]
65
65
  raise InvalidToken.new('Missing user_jwk') if jwk.blank?
66
+ raise InvalidToken.new('Invalid user_id') unless jwt[:user_id] == self_issued_user_id(jwk)
66
67
  public_key = JSON::JWK.decode jwk
67
- user_id_base_string = case public_key
68
- when OpenSSL::PKey::RSA
68
+ jwt = JSON::JWT.decode jwt_string, public_key
69
+ new jwt
70
+ end
71
+
72
+ def self_issued(attributes = {})
73
+ attributes[:user_jwk] ||= JSON::JWK.new attributes.delete(:public_key)
74
+ _attributes_ = {
75
+ iss: 'https://self-issued.me',
76
+ user_id: self_issued_user_id(attributes[:user_jwk])
77
+ }.merge(attributes)
78
+ new _attributes_
79
+ end
80
+
81
+ def self_issued_user_id(jwk)
82
+ user_id_base_string = case jwk[:alg].to_s
83
+ when 'RSA'
69
84
  [jwk[:mod], jwk[:xpo]].join
70
- when OpenSSL::PKey::EC
85
+ when 'EC'
71
86
  raise NotImplementedError.new('Not Implemented Yet')
72
87
  else
73
88
  # Shouldn't reach here. All unknown algorithm error should occurs when decoding JWK
74
89
  raise InvalidToken.new('Unknown Algorithm')
75
90
  end
76
- expected_user_id = UrlSafeBase64.encode64 OpenSSL::Digest::SHA256.digest(user_id_base_string)
77
- raise InvalidToken.new('Invalid user_id') unless jwt[:user_id] == expected_user_id
78
- jwt = JSON::JWT.decode jwt_string, public_key
79
- new jwt
91
+ UrlSafeBase64.encode64 OpenSSL::Digest::SHA256.digest(user_id_base_string)
80
92
  end
81
93
  end
82
94
  end
@@ -0,0 +1,31 @@
1
+ module CryptoSpecHelper
2
+ def rsa_key
3
+ @rsa_key ||= OpenSSL::PKey::RSA.generate 2048
4
+ end
5
+
6
+ def public_key
7
+ @public_key ||= rsa_key.public_key
8
+ end
9
+
10
+ def private_key
11
+ @private_key ||= OpenSSL::PKey::RSA.new rsa_key.export(OpenSSL::Cipher::Cipher.new('DES-EDE3-CBC'), 'pass-phrase'), 'pass-phrase'
12
+ end
13
+
14
+ def ec_key
15
+ @ec_key ||= OpenSSL::PKey::EC.new('secp256k1').generate_key
16
+ end
17
+
18
+ def ec_public_key
19
+ unless @ec_public_key
20
+ @ec_public_key = OpenSSL::PKey::EC.new ec_key
21
+ @ec_public_key.private_key = nil
22
+ end
23
+ @ec_public_key
24
+ end
25
+
26
+ def ec_private_key
27
+ ec_key
28
+ end
29
+ end
30
+
31
+ include CryptoSpecHelper
@@ -0,0 +1 @@
1
+ eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjbGllbnRfaWQiOiJjbGllbnRfaWQiLCJyZXNwb25zZV90eXBlIjoidG9rZW4gaWRfdG9rZW4iLCJyZWRpcmVjdF91cmkiOiJodHRwczovL2NsaWVudC5leGFtcGxlLmNvbSIsInNjb3BlIjoib3BlbmlkIGVtYWlsIiwic3RhdGUiOiJzdGF0ZTEyMzQiLCJub25jZSI6Im5vbmNlMTIzNCIsImRpc3BsYXkiOiJ0b3VjaCIsInByb21wdCI6Im5vbmUiLCJpZF90b2tlbiI6eyJjbGFpbXMiOnsiYWNyIjp7InZhbHVlcyI6WyIyIiwiMyIsIjQiXX19LCJtYXhfYWdlIjoxMH0sInVzZXJpbmZvIjp7ImNsYWltcyI6eyJuYW1lIjp7ImVzc2VudGlhbCI6dHJ1ZX0sImVtYWlsIjp7ImVzc2VudGlhbCI6ZmFsc2V9fX19.MLTDQVPdhAdkJhboM06IRtjHJrvamJ_H2vFGRupXmTA
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe OpenIDConnect::Discovery::Provider::Config::Resource do
4
+ let(:resource) do
5
+ uri = URI.parse 'http://server.example.com'
6
+ OpenIDConnect::Discovery::Provider::Config::Resource.new uri
7
+ end
8
+
9
+ describe '#endpoint' do
10
+ context 'when invalid host' do
11
+ before do
12
+ resource.host = 'hoge*hoge'
13
+ end
14
+
15
+ it do
16
+ expect { resource.endpoint }.to raise_error SWD::Exception
17
+ end
18
+ end
19
+ end
20
+ end
@@ -25,6 +25,16 @@ describe OpenIDConnect::Discovery::Provider::Config do
25
25
  config.user_id_types_supported.should == ["public", "pairwise"]
26
26
  end
27
27
  end
28
+
29
+ context 'when SWD::Exception raised' do
30
+ it do
31
+ expect do
32
+ mock_json :get, endpoint, 'errors/unknown', status: [404, 'Not Found'] do
33
+ OpenIDConnect::Discovery::Provider::Config.discover! provider
34
+ end
35
+ end.to raise_error OpenIDConnect::Discovery::DiscoveryFailed
36
+ end
37
+ end
28
38
  end
29
39
 
30
40
  context 'when OP identifier includes custom port' do
@@ -81,6 +81,16 @@ describe OpenIDConnect::RequestObject do
81
81
  end
82
82
  end
83
83
 
84
+ describe '.fetch' do
85
+ let(:endpoint) { 'https://client.example.com/request.jwk' }
86
+ it do
87
+ mock_json :get, endpoint, 'request_object/signed', format: :jwt do
88
+ request_object = OpenIDConnect::RequestObject.fetch endpoint, 'secret'
89
+ request_object.as_json.should == jsonized.with_indifferent_access
90
+ end
91
+ end
92
+ end
93
+
84
94
  describe '#required?' do
85
95
  it do
86
96
  request_object.user_info.required?(:name).should be_true
@@ -270,4 +270,59 @@ describe OpenIDConnect::ResponseObject::IdToken do
270
270
  end
271
271
  end
272
272
  end
273
+
274
+ describe '.self_issued' do
275
+ subject { self_issued }
276
+ let(:user_jwk) { JSON::JWK.new(public_key) }
277
+ let(:self_issued) do
278
+ klass.self_issued(
279
+ public_key: public_key,
280
+ aud: 'client.example.com',
281
+ exp: 1.week.from_now,
282
+ iat: Time.now
283
+ )
284
+ end
285
+
286
+ [:iss, :user_id, :aud, :exp, :iat, :user_jwk].each do |attribute|
287
+ its(attribute) { should be_present }
288
+ end
289
+ its(:iss) { should == 'https://self-issued.me' }
290
+ its(:user_jwk) { should == user_jwk }
291
+ its(:user_id) { should == OpenIDConnect::ResponseObject::IdToken.self_issued_user_id(user_jwk) }
292
+ end
293
+
294
+ describe '.self_issued_user_id' 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_user_id jwk
299
+ user_id.should == UrlSafeBase64.encode64(
300
+ OpenSSL::Digest::SHA256.digest([jwk[:mod], jwk[:xpo]].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
+ user_id = klass.self_issued_user_id 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
+ user_id = klass.self_issued_user_id jwk
324
+ end.to raise_error OpenIDConnect::ResponseObject::IdToken::InvalidToken
325
+ end
326
+ end
327
+ end
273
328
  end
@@ -35,7 +35,7 @@ describe Rack::OAuth2::Server::Authorize::Extension::IdToken do
35
35
  end
36
36
  end
37
37
 
38
- context 'otherwise' do
38
+ context 'when id_token is missing' do
39
39
  let :app do
40
40
  Rack::OAuth2::Server::Authorize.new do |request, response|
41
41
  response.redirect_uri = redirect_uri
@@ -46,4 +46,23 @@ describe Rack::OAuth2::Server::Authorize::Extension::IdToken do
46
46
  expect { response }.to raise_error AttrRequired::AttrMissing, "'id_token' required."
47
47
  end
48
48
  end
49
+
50
+ context 'when error response' do
51
+ let(:env) { Rack::MockRequest.env_for("/authorize?client_id=client_id") }
52
+ let(:request) { Rack::OAuth2::Server::Authorize::Extension::IdToken::Request.new env }
53
+
54
+ it 'should set protocol_params_location = :fragment' do
55
+ expect { request.bad_request! }.to raise_error(Rack::OAuth2::Server::Authorize::BadRequest) { |e|
56
+ e.protocol_params_location.should == :fragment
57
+ }
58
+ end
59
+ end
60
+
61
+ context 'when openid scope given' do
62
+ let(:env) { Rack::MockRequest.env_for("/authorize?client_id=client_id&scope=openid") }
63
+ let(:request) { Rack::OAuth2::Server::Authorize::Extension::IdToken::Request.new env }
64
+ it do
65
+ request.openid_connect_request?.should be_true
66
+ end
67
+ end
49
68
  end
@@ -3,16 +3,5 @@ require 'cover_me'
3
3
  require 'rspec'
4
4
  require 'openid_connect'
5
5
 
6
- require 'helpers/webmock_helper'
7
-
8
- def rsa
9
- @rsa ||= OpenSSL::PKey::RSA.generate 2048
10
- end
11
-
12
- def public_key
13
- @public_key ||= rsa.public_key
14
- end
15
-
16
- def private_key
17
- @private_key ||= OpenSSL::PKey::RSA.new rsa.export(OpenSSL::Cipher::Cipher.new('DES-EDE3-CBC'), 'pass-phrase'), 'pass-phrase'
18
- end
6
+ require 'helpers/crypto_spec_helper'
7
+ require 'helpers/webmock_helper'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openid_connect
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.3.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-23 00:00:00.000000000 Z
12
+ date: 2012-10-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
@@ -270,6 +270,7 @@ files:
270
270
  - lib/rack/oauth2/server/id_token_response.rb
271
271
  - lib/rack/oauth2/server/resource/error_with_connect_ext.rb
272
272
  - openid_connect.gemspec
273
+ - spec/helpers/crypto_spec_helper.rb
273
274
  - spec/helpers/webmock_helper.rb
274
275
  - spec/mock_response/access_token/bearer.json
275
276
  - spec/mock_response/access_token/bearer_with_id_token.json
@@ -287,6 +288,7 @@ files:
287
288
  - spec/mock_response/id_token.json
288
289
  - spec/mock_response/public_keys/jwk.json
289
290
  - spec/mock_response/public_keys/x509.pem
291
+ - spec/mock_response/request_object/signed.jwt
290
292
  - spec/mock_response/user_info/openid.json
291
293
  - spec/openid_connect/access_token_spec.rb
292
294
  - spec/openid_connect/client/registrar_spec.rb
@@ -296,6 +298,7 @@ files:
296
298
  - spec/openid_connect/discovery/principal/email_spec.rb
297
299
  - spec/openid_connect/discovery/principal/uri_spec.rb
298
300
  - spec/openid_connect/discovery/principal_spec.rb
301
+ - spec/openid_connect/discovery/provider/config/resource_spec.rb
299
302
  - spec/openid_connect/discovery/provider/config/response_spec.rb
300
303
  - spec/openid_connect/discovery/provider/config_spec.rb
301
304
  - spec/openid_connect/discovery/provider_spec.rb
@@ -327,7 +330,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
327
330
  version: '0'
328
331
  segments:
329
332
  - 0
330
- hash: 2386054182410413464
333
+ hash: 4253340027617054014
331
334
  required_rubygems_version: !ruby/object:Gem::Requirement
332
335
  none: false
333
336
  requirements:
@@ -336,7 +339,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
336
339
  version: '0'
337
340
  segments:
338
341
  - 0
339
- hash: 2386054182410413464
342
+ hash: 4253340027617054014
340
343
  requirements: []
341
344
  rubyforge_project:
342
345
  rubygems_version: 1.8.24
@@ -344,6 +347,7 @@ signing_key:
344
347
  specification_version: 3
345
348
  summary: OpenID Connect Server & Client Library
346
349
  test_files:
350
+ - spec/helpers/crypto_spec_helper.rb
347
351
  - spec/helpers/webmock_helper.rb
348
352
  - spec/mock_response/access_token/bearer.json
349
353
  - spec/mock_response/access_token/bearer_with_id_token.json
@@ -361,6 +365,7 @@ test_files:
361
365
  - spec/mock_response/id_token.json
362
366
  - spec/mock_response/public_keys/jwk.json
363
367
  - spec/mock_response/public_keys/x509.pem
368
+ - spec/mock_response/request_object/signed.jwt
364
369
  - spec/mock_response/user_info/openid.json
365
370
  - spec/openid_connect/access_token_spec.rb
366
371
  - spec/openid_connect/client/registrar_spec.rb
@@ -370,6 +375,7 @@ test_files:
370
375
  - spec/openid_connect/discovery/principal/email_spec.rb
371
376
  - spec/openid_connect/discovery/principal/uri_spec.rb
372
377
  - spec/openid_connect/discovery/principal_spec.rb
378
+ - spec/openid_connect/discovery/provider/config/resource_spec.rb
373
379
  - spec/openid_connect/discovery/provider/config/response_spec.rb
374
380
  - spec/openid_connect/discovery/provider/config_spec.rb
375
381
  - spec/openid_connect/discovery/provider_spec.rb