openid_connect 0.3.3 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/Gemfile +1 -9
  2. data/Gemfile.lock +8 -11
  3. data/Rakefile +10 -16
  4. data/VERSION +1 -1
  5. data/lib/openid_connect.rb +1 -1
  6. data/lib/openid_connect/access_token.rb +2 -2
  7. data/lib/openid_connect/client.rb +2 -2
  8. data/lib/openid_connect/client/registrar.rb +16 -15
  9. data/lib/openid_connect/discovery/principal.rb +5 -5
  10. data/lib/openid_connect/discovery/provider/config.rb +1 -1
  11. data/lib/openid_connect/discovery/provider/config/resource.rb +4 -3
  12. data/lib/openid_connect/discovery/provider/config/response.rb +41 -1
  13. data/lib/openid_connect/request_object/claimable.rb +2 -2
  14. data/lib/openid_connect/response_object/id_token.rb +1 -1
  15. data/lib/openid_connect/response_object/user_info/open_id.rb +5 -5
  16. data/lib/rack/oauth2/server/authorize/error_with_connect_ext.rb +7 -7
  17. data/lib/rack/oauth2/server/id_token_response.rb +1 -1
  18. data/openid_connect.gemspec +1 -5
  19. data/spec/mock_response/public_keys/jwk.json +7 -0
  20. data/spec/mock_response/public_keys/x509.pem +21 -0
  21. data/spec/openid_connect/access_token_spec.rb +23 -23
  22. data/spec/openid_connect/client/registrar_spec.rb +45 -45
  23. data/spec/openid_connect/client_spec.rb +12 -12
  24. data/spec/openid_connect/connect_object_spec.rb +6 -6
  25. data/spec/openid_connect/debugger/request_filter_spec.rb +1 -1
  26. data/spec/openid_connect/discovery/principal_spec.rb +5 -5
  27. data/spec/openid_connect/discovery/provider/config/response_spec.rb +265 -3
  28. data/spec/openid_connect/discovery/provider/config_spec.rb +11 -0
  29. data/spec/openid_connect/discovery/provider_spec.rb +3 -3
  30. data/spec/openid_connect/request_object_spec.rb +36 -36
  31. data/spec/openid_connect/response_object/id_token_spec.rb +26 -26
  32. data/spec/openid_connect/response_object/user_info/open_id_spec.rb +7 -7
  33. data/spec/rack/oauth2/server/authorize/extension/code_and_id_token_and_token_spec.rb +7 -7
  34. data/spec/rack/oauth2/server/authorize/extension/code_and_id_token_spec.rb +6 -6
  35. data/spec/rack/oauth2/server/authorize/extension/id_token_and_token_spec.rb +7 -7
  36. data/spec/rack/oauth2/server/authorize/extension/id_token_spec.rb +6 -6
  37. data/spec/rack/oauth2/server/token/authorization_code_spec.rb +14 -14
  38. data/spec/rack/oauth2/server/token/refresh_token_spec.rb +13 -13
  39. data/spec/spec_helper.rb +1 -3
  40. metadata +15 -11
data/Gemfile CHANGED
@@ -1,10 +1,2 @@
1
- source "http://rubygems.org"
2
-
3
- group :test do
4
- platforms :jruby do
5
- gem 'jruby-openssl', '>= 0.7'
6
- end
7
- end
8
-
9
- # Specify your gem's dependencies in openid_connect.gemspec
1
+ source :rubygems
10
2
  gemspec
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- openid_connect (0.3.2)
4
+ openid_connect (0.3.4)
5
5
  activemodel (>= 3)
6
6
  attr_required (>= 0.0.5)
7
7
  json (>= 1.4.3)
@@ -23,8 +23,7 @@ GEM
23
23
  multi_json (~> 1.0)
24
24
  addressable (2.3.2)
25
25
  attr_required (0.0.5)
26
- bouncy-castle-java (1.5.0146.1)
27
- builder (3.0.3)
26
+ builder (3.0.4)
28
27
  configatron (2.9.1)
29
28
  yamler (>= 0.1.0)
30
29
  cover_me (1.2.0)
@@ -33,12 +32,11 @@ GEM
33
32
  crack (0.3.1)
34
33
  diff-lcs (1.1.3)
35
34
  hashie (1.2.0)
36
- httpclient (2.2.7)
35
+ httpclient (2.3.0.1)
37
36
  i18n (0.6.1)
38
- jruby-openssl (0.7.7)
39
- bouncy-castle-java (>= 1.5.0146.1)
40
37
  json (1.7.5)
41
- json-jwt (0.3.0)
38
+ json (1.7.5-java)
39
+ json-jwt (0.3.2)
42
40
  activesupport (>= 2.3)
43
41
  i18n
44
42
  json (>= 1.4.3)
@@ -51,7 +49,7 @@ GEM
51
49
  multi_json (1.3.6)
52
50
  polyglot (0.3.3)
53
51
  rack (1.4.1)
54
- rack-oauth2 (0.14.9)
52
+ rack-oauth2 (1.0.0)
55
53
  activesupport (>= 2.3)
56
54
  attr_required (>= 0.0.5)
57
55
  httpclient (>= 2.2.0.2)
@@ -67,13 +65,13 @@ GEM
67
65
  rspec-expectations (2.11.3)
68
66
  diff-lcs (~> 1.1.3)
69
67
  rspec-mocks (2.11.3)
70
- swd (0.2.0)
68
+ swd (0.2.1)
71
69
  activesupport (>= 3)
72
70
  attr_required (>= 0.0.5)
73
71
  httpclient (>= 2.2.1)
74
72
  i18n
75
73
  json (>= 1.4.3)
76
- treetop (1.4.10)
74
+ treetop (1.4.11)
77
75
  polyglot
78
76
  polyglot (>= 0.3.1)
79
77
  tzinfo (0.3.33)
@@ -94,7 +92,6 @@ PLATFORMS
94
92
 
95
93
  DEPENDENCIES
96
94
  cover_me (>= 1.2.0)
97
- jruby-openssl (>= 0.7)
98
95
  openid_connect!
99
96
  rake (>= 0.8)
100
97
  rspec (>= 2)
data/Rakefile CHANGED
@@ -4,22 +4,16 @@ Bundler::GemHelper.install_tasks
4
4
  require 'rspec/core/rake_task'
5
5
  RSpec::Core::RakeTask.new(:spec)
6
6
 
7
- if RUBY_VERSION >= '1.9'
8
- namespace :cover_me do
9
- desc "Generates and opens code coverage report."
10
- task :report do
11
- require 'cover_me'
12
- CoverMe.complete!
13
- end
14
- end
15
- task :spec do
16
- Rake::Task['cover_me:report'].invoke
17
- end
18
- else
19
- RSpec::Core::RakeTask.new(:rcov) do |spec|
20
- spec.rcov = true
21
- spec.rcov_opts = ['-Ilib -Ispec --exclude spec,gems']
7
+ namespace :cover_me do
8
+ desc "Generates and opens code coverage report."
9
+ task :report do
10
+ require 'cover_me'
11
+ CoverMe.complete!
22
12
  end
23
13
  end
24
14
 
25
- task :default => :spec
15
+ task :spec do
16
+ Rake::Task['cover_me:report'].invoke
17
+ end
18
+
19
+ task default: :spec
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.3
1
+ 0.3.4
@@ -54,7 +54,7 @@ module OpenIDConnect
54
54
 
55
55
  def self.http_client
56
56
  _http_client_ = HTTPClient.new(
57
- :agent_name => "OpenIDConnect (#{VERSION})"
57
+ agent_name: "OpenIDConnect (#{VERSION})"
58
58
  )
59
59
  _http_client_.request_filter << Debugger::RequestFilter.new if debugging?
60
60
  http_config.try(:call, _http_client_)
@@ -10,7 +10,7 @@ module OpenIDConnect
10
10
 
11
11
  def user_info!(schema = :openid)
12
12
  hash = resource_request do
13
- get client.user_info_uri, :schema => schema
13
+ get client.user_info_uri, schema: schema
14
14
  end
15
15
  ResponseObject::UserInfo::OpenID.new hash
16
16
  end
@@ -21,7 +21,7 @@ module OpenIDConnect
21
21
  res = yield
22
22
  case res.status
23
23
  when 200
24
- JSON.parse(res.body, :symbolize_names => true)
24
+ JSON.parse res.body, symbolize_names: true
25
25
  when 400
26
26
  raise BadRequest.new('API Access Faild', res)
27
27
  when 401
@@ -26,10 +26,10 @@ module OpenIDConnect
26
26
  end
27
27
 
28
28
  def handle_success_response(response)
29
- token_hash = JSON.parse(response.body, :symbolize_names => true)
29
+ token_hash = JSON.parse response.body, symbolize_names: true
30
30
  case token_type = token_hash[:token_type].try(:downcase)
31
31
  when 'bearer'
32
- AccessToken.new token_hash.merge(:client => self)
32
+ AccessToken.new token_hash.merge(client: self)
33
33
  else
34
34
  raise Exception.new("Unexpected Token Type: #{token_type}")
35
35
  end
@@ -54,16 +54,16 @@ module OpenIDConnect
54
54
  alias_method_chain _attr_, :split
55
55
  end
56
56
 
57
- validates :type, :presence => true
58
- validates :client_id, :presence => {:if => lambda { |c| ['client_update', 'rotate_secret'].include?(c.type.to_s) }}
59
- validates :sector_identifier_url, :presence => {:if => :sector_identifier_required?}
57
+ validates :type, presence: true
58
+ validates :client_id, presence: {if: ->(c) { ['client_update', 'rotate_secret'].include?(c.type.to_s) }}
59
+ validates :sector_identifier_url, presence: {if: :sector_identifier_required?}
60
60
 
61
- validates :type, :inclusion => {:in => ['client_associate', 'rotate_secret', 'client_update']}
62
- validates :application_type, :inclusion => {:in => ['native', 'web']}, :allow_nil => true
63
- validates :user_id_type, :inclusion => {:in => ['pairwise', 'public']}, :allow_nil => true
64
- validates :token_endpoint_auth_type, :inclusion => {
65
- :in => ['client_secret_post', 'client_secret_basic', 'client_secret_jwt', 'private_key_jwt']
66
- }, :allow_nil => true
61
+ validates :type, inclusion: {in: ['client_associate', 'rotate_secret', 'client_update']}
62
+ validates :application_type, inclusion: {in: ['native', 'web']}, allow_nil: true
63
+ validates :user_id_type, inclusion: {in: ['pairwise', 'public']}, allow_nil: true
64
+ validates :token_endpoint_auth_type, inclusion: {
65
+ in: ['client_secret_post', 'client_secret_basic', 'client_secret_jwt', 'private_key_jwt']
66
+ }, allow_nil: true
67
67
 
68
68
  validates(
69
69
  :logo_url,
@@ -73,7 +73,8 @@ module OpenIDConnect
73
73
  :x509_url,
74
74
  :x509_encryption_url,
75
75
  :sector_identifier_url,
76
- :url => true, :allow_nil => true
76
+ url: true,
77
+ allow_nil: true
77
78
  )
78
79
 
79
80
  validate :validate_contacts
@@ -209,7 +210,7 @@ module OpenIDConnect
209
210
  access_token
210
211
  else
211
212
  Rack::OAuth2::AccessToken::Bearer.new(
212
- :access_token => access_token
213
+ access_token: access_token
213
214
  )
214
215
  end
215
216
  end
@@ -225,11 +226,11 @@ module OpenIDConnect
225
226
  end
226
227
 
227
228
  def handle_success_response(response)
228
- credentials = JSON.parse(response.body, :symbolize_names => true)
229
+ credentials = JSON.parse response.body, symbolize_names: true
229
230
  Client.new(
230
- :identifier => credentials[:client_id],
231
- :secret => credentials[:client_secret],
232
- :expires_in => credentials[:expires_in]
231
+ identifier: credentials[:client_id],
232
+ secret: credentials[:client_secret],
233
+ expires_in: credentials[:expires_in]
233
234
  )
234
235
  end
235
236
 
@@ -16,11 +16,11 @@ module OpenIDConnect
16
16
 
17
17
  def discover!(cache_options = {})
18
18
  SWD.discover!(
19
- :principal => identifier,
20
- :service => Provider::SERVICE_URI,
21
- :host => host,
22
- :port => port,
23
- :cache => cache_options
19
+ principal: identifier,
20
+ service: Provider::SERVICE_URI,
21
+ host: host,
22
+ port: port,
23
+ cache: cache_options
24
24
  )
25
25
  rescue SWD::Exception => e
26
26
  raise DiscoveryFailed.new(e.message)
@@ -4,7 +4,7 @@ module OpenIDConnect
4
4
  class Config
5
5
  def self.discover!(identifier, cache_options = {})
6
6
  principal = Principal.parse(identifier)
7
- Resource.new(principal.host).discover!(cache_options)
7
+ Resource.new(principal).discover!(cache_options)
8
8
  rescue SWD::Exception => e
9
9
  raise DiscoveryFailed.new(e.message)
10
10
  end
@@ -7,14 +7,15 @@ module OpenIDConnect
7
7
 
8
8
  class Expired < SWD::Resource::Expired; end
9
9
 
10
- def initialize(host)
11
- @host = host
10
+ def initialize(principal)
11
+ @host = principal.host
12
+ @port = principal.port unless [80, 443].include?(principal.port)
12
13
  @path ||= '/.well-known/openid-configuration'
13
14
  attr_missing!
14
15
  end
15
16
 
16
17
  def endpoint
17
- SWD.url_builder.build [nil, host, nil, path, nil, nil]
18
+ SWD.url_builder.build [nil, host, port, path, nil, nil]
18
19
  rescue URI::Error => e
19
20
  raise SWD::Exception.new(e.message)
20
21
  end
@@ -17,7 +17,7 @@ module OpenIDConnect
17
17
  :jwk_url,
18
18
  :jwk_encryption_url,
19
19
  :x509_url,
20
- :x509_encryption_ur,
20
+ :x509_encryption_url,
21
21
  :registration_endpoint,
22
22
  :scopes_supported,
23
23
  :response_types_supported,
@@ -52,6 +52,46 @@ module OpenIDConnect
52
52
  value.nil?
53
53
  end
54
54
  end
55
+
56
+ def signing_key
57
+ x509_public_key || jwk_public_key
58
+ end
59
+
60
+ def encryption_key
61
+ if x509_encryption_url
62
+ x509_public_key :for_encryption
63
+ elsif jwk_encryption_url
64
+ jwk_public_key :for_encryption
65
+ else
66
+ signing_key
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ def x509_public_key(for_encryption = false)
73
+ endpoint = if for_encryption
74
+ x509_encryption_url || x509_url
75
+ else
76
+ x509_url
77
+ end
78
+ if endpoint
79
+ cert = OpenSSL::X509::Certificate.new OpenIDConnect.http_client.get_content(endpoint)
80
+ cert.public_key
81
+ end
82
+ end
83
+
84
+ def jwk_public_key(for_encryption = false)
85
+ endpoint = if for_encryption
86
+ jwk_encryption_url || jwk_url
87
+ else
88
+ jwk_url
89
+ end
90
+ if endpoint
91
+ jwk_set = JSON.parse OpenIDConnect.http_client.get_content(endpoint), symbolize_names: true
92
+ JSON::JWK.decode jwk_set[:keys].first
93
+ end
94
+ end
55
95
  end
56
96
  end
57
97
  end
@@ -15,11 +15,11 @@ module OpenIDConnect
15
15
  _claims_[key] = case value
16
16
  when :optional, :voluntary
17
17
  {
18
- :essential => false
18
+ essential: false
19
19
  }
20
20
  when :required, :essential
21
21
  {
22
- :essential => true
22
+ essential: true
23
23
  }
24
24
  else
25
25
  value
@@ -40,7 +40,7 @@ module OpenIDConnect
40
40
  public_key = JSON::JWK.decode jwk
41
41
  user_id_base_string = case public_key
42
42
  when OpenSSL::PKey::RSA
43
- [jwk[:mod], jwk[:exp]].join
43
+ [jwk[:mod], jwk[:xpo]].join
44
44
  when OpenSSL::PKey::EC
45
45
  raise NotImplementedError.new('Not Implemented Yet')
46
46
  else
@@ -24,11 +24,11 @@ module OpenIDConnect
24
24
  :phone_number
25
25
  )
26
26
 
27
- validates :email_verified, :inclusion => {:in => [true, false]}, :allow_nil => true
28
- validates :gender, :inclusion => {:in => ['male', 'female']}, :allow_nil => true
29
- validates :zoneinfo, :inclusion => {:in => TZInfo::TimezoneProxy.all.collect(&:name)}, :allow_nil => true
30
- validates :profile, :picture, :website, :url => true, :allow_nil => true
31
- validates :email, :email => true, :allow_nil => true
27
+ validates :email_verified, inclusion: {in: [true, false]}, allow_nil: true
28
+ validates :gender, inclusion: {in: ['male', 'female']}, allow_nil: true
29
+ validates :zoneinfo, inclusion: {in: TZInfo::TimezoneProxy.all.collect(&:name)}, allow_nil: true
30
+ validates :profile, :picture, :website, url: true, allow_nil: true
31
+ validates :email, email: true, allow_nil: true
32
32
  validate :validate_address
33
33
  validate :require_at_least_one_attributes
34
34
  # TODO: validate locale
@@ -4,13 +4,13 @@ module Rack
4
4
  class Authorize
5
5
  module ErrorWithConnectExt
6
6
  DEFAULT_DESCRIPTION = {
7
- :invalid_redirect_uri => 'The redirect_uri in the request does not match any of pre-registered redirect_uris.',
8
- :interaction_required => 'End-User interaction required.',
9
- :login_required => 'End-User authentication required.',
10
- :session_selection_required => 'The End-User is required to select a session at the Authorization Server.',
11
- :consent_required => 'End-User consent required.',
12
- :invalid_request_uri => 'The request_uri in the request returns an error or invalid data.',
13
- :invalid_openid_request_object => 'The request parameter contains an invalid OpenID Request Object.'
7
+ invalid_redirect_uri: 'The redirect_uri in the request does not match any of pre-registered redirect_uris.',
8
+ interaction_required: 'End-User interaction required.',
9
+ login_required: 'End-User authentication required.',
10
+ session_selection_required: 'The End-User is required to select a session at the Authorization Server.',
11
+ consent_required: 'End-User consent required.',
12
+ invalid_request_uri: 'The request_uri in the request returns an error or invalid data.',
13
+ invalid_openid_request_object: 'The request parameter contains an invalid OpenID Request Object.'
14
14
  }
15
15
 
16
16
  def self.included(klass)
@@ -9,7 +9,7 @@ module Rack::OAuth2::Server
9
9
 
10
10
  def protocol_params_with_id_token
11
11
  protocol_params_without_id_token.merge(
12
- :id_token => id_token
12
+ id_token: id_token
13
13
  )
14
14
  end
15
15
  alias_method_chain :protocol_params, :id_token
@@ -20,11 +20,7 @@ Gem::Specification.new do |s|
20
20
  s.add_runtime_dependency "swd", ">= 0.1.2"
21
21
  s.add_runtime_dependency "rack-oauth2", ">= 0.14.2"
22
22
  s.add_development_dependency "rake", ">= 0.8"
23
- if RUBY_VERSION >= '1.9'
24
- s.add_development_dependency "cover_me", ">= 1.2.0"
25
- else
26
- s.add_development_dependency "rcov", ">= 0.9"
27
- end
28
23
  s.add_development_dependency "rspec", ">= 2"
29
24
  s.add_development_dependency "webmock", ">= 1.6.2"
25
+ s.add_development_dependency "cover_me", ">= 1.2.0"
30
26
  end
@@ -0,0 +1,7 @@
1
+ {
2
+ "keys": [{
3
+ "alg": "RSA",
4
+ "xpo": "AQAB",
5
+ "mod": "u4liYNFzgsRr1ERdUY7CY6r4nefi3RzIhK5fdPgdZSMEEflACWAuJu21_TcDpbZ1-6Kbq7zShFsVTAnBkWdO7EP1Rsn11fZpi9m_zEq_uRY-4RpNwp3S9xSdoQ4F3-js1EMaDQ6km0-c0gvr_TyhFqDj_6w_Bb0vFptfGXwfKewPPnhsi7GJ62ihZ32PzxOvEIYcaoXr9xaeudYD3BzWSDmjKGA7PMaEuBhScdUAoibCmsKB-yAGsz2amHnUhcl4B_EBs6wk65Y7ge0ZQJUOGPdUQL49VuALKmr7cMhHKh5KuQmPAi_20K2uZL_EFDaObDWZrclx98s0DmfTRKINtw"
6
+ }]
7
+ }
@@ -0,0 +1,21 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDeDCCAmACCQDFeFSXWEnHxDANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJK
3
+ UDEOMAwGA1UECAwFVG9reW8xEDAOBgNVBAcMB1NoaWJ1eWExITAfBgNVBAoMGElu
4
+ dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEMMAoGA1UEAwwDTm92MRwwGgYJKoZIhvcN
5
+ AQkBFg1ub3ZAbWF0YWtlLmpwMB4XDTExMDkxMzEzMjIzNFoXDTEyMDkxMjEzMjIz
6
+ NFowfjELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRva3lvMRAwDgYDVQQHDAdTaGli
7
+ dXlhMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDDAKBgNVBAMM
8
+ A05vdjEcMBoGCSqGSIb3DQEJARYNbm92QG1hdGFrZS5qcDCCASIwDQYJKoZIhvcN
9
+ AQEBBQADggEPADCCAQoCggEBAKSsm7NFmh1P8uHB8Vm5vFs4+uh7XMhZ+xYd5/vf
10
+ ak17ucjWt9DEWCGH0g8HvSVXNSVKBsONcqtkrXRgSeNB8YnIYxPmKKX7twefEJYC
11
+ b06FG1g+IJkwxoDBsUMbb9RJ9snnWsp0O97A6SCvtdiSQ2Oeab3/jwokkPTo8WS4
12
+ lRipQpQ7rOOP7r9t+9G/SDdiYhDhfmuyQamkxGCz6V2qClg0pyTaJ6+/bS9E+4ri
13
+ ZjtZe9OaDt2NE0PiDS2Oo5yhv0abL8rxjZ8D/aTL3D9aYSrFmddKH7roSRkafCMU
14
+ C/UX80/OzrxdEQUjtVO94dPWD/nKK1g7JyiIuk280aTeWA8CAwEAATANBgkqhkiG
15
+ 9w0BAQsFAAOCAQEAdiNDw9z6U8lIF0NWVObeGqoxn/MSp/W5S56ts3agw0meqc1J
16
+ gUPkncXbpjZ/wX0Y3pupmGBIO0XAHPhjyCu3HhplhaVxSNqKEg9wB3huYaMZ2Kbi
17
+ +Wy77hLO2hOYk8vI/ok5oW0lhhpA0o4GzbyV4SA3nZgT0u8YXC7cqAHqI9KsBU5z
18
+ 62mjlptCR/b10xTlC13AtbdDM6s1hWP9XpDrm6Kxgfu7nKQ1Q31ag1Ukm9Gw8qcl
19
+ ILxZxqbqGy/q1C+6ObTmGtiVbJTs+W8u5BPg9S49O6qIhVN5wWCT4lRrlpXpYA3a
20
+ TTVBULB1g7Iod2g+kF0qAXnwqGvZ5LOgwFfmcw==
21
+ -----END CERTIFICATE-----