openid_connect 0.3.6 → 0.3.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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