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.
- data/Gemfile +1 -9
- data/Gemfile.lock +8 -11
- data/Rakefile +10 -16
- data/VERSION +1 -1
- data/lib/openid_connect.rb +1 -1
- data/lib/openid_connect/access_token.rb +2 -2
- data/lib/openid_connect/client.rb +2 -2
- data/lib/openid_connect/client/registrar.rb +16 -15
- data/lib/openid_connect/discovery/principal.rb +5 -5
- data/lib/openid_connect/discovery/provider/config.rb +1 -1
- data/lib/openid_connect/discovery/provider/config/resource.rb +4 -3
- data/lib/openid_connect/discovery/provider/config/response.rb +41 -1
- data/lib/openid_connect/request_object/claimable.rb +2 -2
- data/lib/openid_connect/response_object/id_token.rb +1 -1
- data/lib/openid_connect/response_object/user_info/open_id.rb +5 -5
- data/lib/rack/oauth2/server/authorize/error_with_connect_ext.rb +7 -7
- data/lib/rack/oauth2/server/id_token_response.rb +1 -1
- data/openid_connect.gemspec +1 -5
- data/spec/mock_response/public_keys/jwk.json +7 -0
- data/spec/mock_response/public_keys/x509.pem +21 -0
- data/spec/openid_connect/access_token_spec.rb +23 -23
- data/spec/openid_connect/client/registrar_spec.rb +45 -45
- data/spec/openid_connect/client_spec.rb +12 -12
- data/spec/openid_connect/connect_object_spec.rb +6 -6
- data/spec/openid_connect/debugger/request_filter_spec.rb +1 -1
- data/spec/openid_connect/discovery/principal_spec.rb +5 -5
- data/spec/openid_connect/discovery/provider/config/response_spec.rb +265 -3
- data/spec/openid_connect/discovery/provider/config_spec.rb +11 -0
- data/spec/openid_connect/discovery/provider_spec.rb +3 -3
- data/spec/openid_connect/request_object_spec.rb +36 -36
- data/spec/openid_connect/response_object/id_token_spec.rb +26 -26
- data/spec/openid_connect/response_object/user_info/open_id_spec.rb +7 -7
- data/spec/rack/oauth2/server/authorize/extension/code_and_id_token_and_token_spec.rb +7 -7
- data/spec/rack/oauth2/server/authorize/extension/code_and_id_token_spec.rb +6 -6
- data/spec/rack/oauth2/server/authorize/extension/id_token_and_token_spec.rb +7 -7
- data/spec/rack/oauth2/server/authorize/extension/id_token_spec.rb +6 -6
- data/spec/rack/oauth2/server/token/authorization_code_spec.rb +14 -14
- data/spec/rack/oauth2/server/token/refresh_token_spec.rb +13 -13
- data/spec/spec_helper.rb +1 -3
- metadata +15 -11
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
openid_connect (0.3.
|
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
|
-
|
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.
|
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
|
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.
|
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.
|
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.
|
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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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 :
|
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.
|
1
|
+
0.3.4
|
data/lib/openid_connect.rb
CHANGED
@@ -54,7 +54,7 @@ module OpenIDConnect
|
|
54
54
|
|
55
55
|
def self.http_client
|
56
56
|
_http_client_ = HTTPClient.new(
|
57
|
-
:
|
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, :
|
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
|
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
|
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(:
|
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, :
|
58
|
-
validates :client_id, :
|
59
|
-
validates :sector_identifier_url, :
|
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, :
|
62
|
-
validates :application_type, :
|
63
|
-
validates :user_id_type, :
|
64
|
-
validates :token_endpoint_auth_type, :
|
65
|
-
:
|
66
|
-
}, :
|
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
|
-
:
|
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
|
-
:
|
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
|
229
|
+
credentials = JSON.parse response.body, symbolize_names: true
|
229
230
|
Client.new(
|
230
|
-
:
|
231
|
-
:
|
232
|
-
:
|
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
|
-
:
|
20
|
-
:
|
21
|
-
:host
|
22
|
-
:port
|
23
|
-
:
|
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
|
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(
|
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,
|
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
|
-
:
|
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
|
@@ -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[:
|
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, :
|
28
|
-
validates :gender,
|
29
|
-
validates :zoneinfo,
|
30
|
-
validates :profile, :picture, :website, :
|
31
|
-
validates :email, :
|
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
|
-
:
|
8
|
-
:
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
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)
|
data/openid_connect.gemspec
CHANGED
@@ -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-----
|