openid_connect 0.5.1 → 0.6.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -2
- data/VERSION +1 -1
- data/lib/openid_connect/access_token.rb +3 -2
- data/lib/openid_connect/client.rb +9 -5
- data/lib/openid_connect/client/registrar.rb +21 -15
- data/lib/openid_connect/discovery/provider/config/response.rb +23 -16
- data/lib/openid_connect/request_object.rb +11 -12
- data/lib/openid_connect/response_object/id_token.rb +14 -12
- data/lib/openid_connect/response_object/user_info/open_id.rb +3 -1
- data/spec/mock_response/discovery/config.json +2 -1
- data/spec/openid_connect/access_token_spec.rb +1 -1
- data/spec/openid_connect/client/registrar_spec.rb +19 -19
- data/spec/openid_connect/discovery/provider/config_spec.rb +3 -2
- data/spec/openid_connect/request_object_spec.rb +7 -7
- data/spec/openid_connect/response_object/id_token_spec.rb +19 -19
- data/spec/openid_connect/response_object/user_info/open_id_spec.rb +3 -3
- data/spec/rack/oauth2/server/authorize/extension/code_and_id_token_and_token_spec.rb +1 -1
- data/spec/rack/oauth2/server/authorize/extension/code_and_id_token_spec.rb +1 -1
- data/spec/rack/oauth2/server/authorize/extension/id_token_and_token_spec.rb +1 -1
- data/spec/rack/oauth2/server/authorize/extension/id_token_spec.rb +1 -1
- data/spec/rack/oauth2/server/token/authorization_code_spec.rb +1 -1
- data/spec/rack/oauth2/server/token/refresh_token_spec.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77b0fff4702e56386e8fc0e50c10cf58ab662d0f
|
4
|
+
data.tar.gz: 1adf047cf6615943b05ed5b7aa34ae504ce2d9e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 915d6d6a304106f2862a8c0235a63153145c454526265a1bf1e1cf1f27eb72df2379a73b719fb6c31b5ae43bdae5d6ba3ceaffeb37edd09724ae6ac533572470
|
7
|
+
data.tar.gz: 47963961ff61a3d530787c238c5ed57b028b07eb48e1558483277906f27988ca66740951bc2764a9ede790ac0584dda7cbe276ec12c0e584cb538f53d9fd4ba8
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
openid_connect (0.
|
4
|
+
openid_connect (0.6.0)
|
5
5
|
activemodel (>= 3)
|
6
6
|
attr_required (>= 0.0.5)
|
7
7
|
json (>= 1.4.3)
|
@@ -36,7 +36,8 @@ GEM
|
|
36
36
|
httpclient (2.3.3)
|
37
37
|
i18n (0.6.4)
|
38
38
|
json (1.7.7)
|
39
|
-
json
|
39
|
+
json (1.7.7-java)
|
40
|
+
json-jwt (0.4.3)
|
40
41
|
activesupport (>= 2.3)
|
41
42
|
i18n
|
42
43
|
multi_json (>= 1.3)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
@@ -8,12 +8,13 @@ module OpenIDConnect
|
|
8
8
|
@token_type = :bearer
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
11
|
+
def userinfo!(schema = :openid)
|
12
12
|
hash = resource_request do
|
13
|
-
get client.
|
13
|
+
get client.userinfo_uri, schema: schema
|
14
14
|
end
|
15
15
|
ResponseObject::UserInfo::OpenID.new hash
|
16
16
|
end
|
17
|
+
alias_method :user_info!, :userinfo!
|
17
18
|
|
18
19
|
private
|
19
20
|
|
@@ -1,10 +1,13 @@
|
|
1
1
|
module OpenIDConnect
|
2
2
|
class Client < Rack::OAuth2::Client
|
3
|
-
attr_optional :
|
3
|
+
attr_optional :userinfo_endpoint, :expires_in
|
4
|
+
alias_method :user_info_endpoint, :userinfo_endpoint
|
5
|
+
alias_method :user_info_endpoint=, :userinfo_endpoint=
|
4
6
|
|
5
7
|
def initialize(attributes = {})
|
6
|
-
|
7
|
-
|
8
|
+
attributes[:userinfo_endpoint] ||= attributes[:user_info_endpoint]
|
9
|
+
super attributes
|
10
|
+
self.userinfo_endpoint ||= '/user_info'
|
8
11
|
end
|
9
12
|
|
10
13
|
def authorization_uri(params = {})
|
@@ -13,9 +16,10 @@ module OpenIDConnect
|
|
13
16
|
super
|
14
17
|
end
|
15
18
|
|
16
|
-
def
|
17
|
-
absolute_uri_for
|
19
|
+
def userinfo_uri
|
20
|
+
absolute_uri_for userinfo_endpoint
|
18
21
|
end
|
22
|
+
alias_method :user_info_uri, :userinfo_uri
|
19
23
|
|
20
24
|
private
|
21
25
|
|
@@ -6,21 +6,22 @@ module OpenIDConnect
|
|
6
6
|
class RegistrationFailed < HttpError; end
|
7
7
|
|
8
8
|
singular_attributes = [
|
9
|
-
:
|
9
|
+
:operation,
|
10
10
|
:client_id,
|
11
11
|
:client_secret,
|
12
12
|
:access_token,
|
13
13
|
:application_type,
|
14
|
-
:
|
14
|
+
:client_name,
|
15
15
|
:logo_url,
|
16
|
-
:
|
16
|
+
:token_endpoint_auth_method,
|
17
17
|
:policy_url,
|
18
|
+
:tos_url,
|
18
19
|
:jwk_url,
|
19
20
|
:jwk_encryption_url,
|
20
21
|
:x509_url,
|
21
22
|
:x509_encryption_url,
|
22
23
|
:sector_identifier_url,
|
23
|
-
:
|
24
|
+
:subject_type,
|
24
25
|
:request_object_signing_alg,
|
25
26
|
:userinfo_signed_response_alg,
|
26
27
|
:userinfo_encrypted_response_alg,
|
@@ -30,7 +31,9 @@ module OpenIDConnect
|
|
30
31
|
:id_token_encrypted_response_enc,
|
31
32
|
:default_max_age,
|
32
33
|
:require_auth_time,
|
33
|
-
:default_acr
|
34
|
+
:default_acr,
|
35
|
+
:initiate_login_uri,
|
36
|
+
:post_logout_redirect_url
|
34
37
|
]
|
35
38
|
plurar_attributes = [
|
36
39
|
:contacts,
|
@@ -52,25 +55,28 @@ module OpenIDConnect
|
|
52
55
|
alias_method_chain _attr_, :split
|
53
56
|
end
|
54
57
|
|
55
|
-
validates :
|
56
|
-
validates :client_id, presence: {if: ->(c) { ['client_update', 'rotate_secret'].include?(c.
|
58
|
+
validates :operation, presence: true
|
59
|
+
validates :client_id, presence: {if: ->(c) { ['client_update', 'rotate_secret'].include?(c.operation.to_s) }}
|
57
60
|
validates :sector_identifier_url, presence: {if: :sector_identifier_required?}
|
58
61
|
|
59
|
-
validates :
|
62
|
+
validates :operation, inclusion: {in: ['client_register', 'rotate_secret', 'client_update']}
|
60
63
|
validates :application_type, inclusion: {in: ['native', 'web']}, allow_nil: true
|
61
|
-
validates :
|
62
|
-
validates :
|
64
|
+
validates :subject_type, inclusion: {in: ['pairwise', 'public']}, allow_nil: true
|
65
|
+
validates :token_endpoint_auth_method, inclusion: {
|
63
66
|
in: ['client_secret_post', 'client_secret_basic', 'client_secret_jwt', 'private_key_jwt']
|
64
67
|
}, allow_nil: true
|
65
68
|
|
66
69
|
validates(
|
67
70
|
:logo_url,
|
68
71
|
:policy_url,
|
72
|
+
:tos_url,
|
69
73
|
:jwk_url,
|
70
74
|
:jwk_encryption_url,
|
71
75
|
:x509_url,
|
72
76
|
:x509_encryption_url,
|
73
77
|
:sector_identifier_url,
|
78
|
+
:initiate_login_uri,
|
79
|
+
:post_logout_redirect_url,
|
74
80
|
url: true,
|
75
81
|
allow_nil: true
|
76
82
|
)
|
@@ -128,18 +134,18 @@ module OpenIDConnect
|
|
128
134
|
end
|
129
135
|
end
|
130
136
|
|
131
|
-
def
|
132
|
-
self.
|
137
|
+
def register!
|
138
|
+
self.operation = 'client_register'
|
133
139
|
post!
|
134
140
|
end
|
135
141
|
|
136
142
|
def rotate_secret!
|
137
|
-
self.
|
143
|
+
self.operation = 'rotate_secret'
|
138
144
|
post!
|
139
145
|
end
|
140
146
|
|
141
147
|
def update!
|
142
|
-
self.
|
148
|
+
self.operation = 'client_update'
|
143
149
|
post!
|
144
150
|
end
|
145
151
|
|
@@ -150,7 +156,7 @@ module OpenIDConnect
|
|
150
156
|
private
|
151
157
|
|
152
158
|
def sector_identifier_required?
|
153
|
-
|
159
|
+
subject_type == 'pairwise' &&
|
154
160
|
sector_identifier.blank?
|
155
161
|
end
|
156
162
|
|
@@ -11,7 +11,7 @@ module OpenIDConnect
|
|
11
11
|
:issuer,
|
12
12
|
:authorization_endpoint,
|
13
13
|
:token_endpoint,
|
14
|
-
:
|
14
|
+
:userinfo_endpoint,
|
15
15
|
:refresh_session_endpoint,
|
16
16
|
:check_session_endpoint,
|
17
17
|
:end_session_endpoint,
|
@@ -22,30 +22,41 @@ module OpenIDConnect
|
|
22
22
|
:registration_endpoint,
|
23
23
|
:scopes_supported,
|
24
24
|
:response_types_supported,
|
25
|
-
:
|
26
|
-
:
|
27
|
-
:
|
28
|
-
:
|
29
|
-
:
|
25
|
+
:acr_values_supported,
|
26
|
+
:subject_types_supported,
|
27
|
+
:claims_supported,
|
28
|
+
:userinfo_signing_alg_values_supported,
|
29
|
+
:userinfo_encryption_alg_values_supported,
|
30
|
+
:userinfo_encryption_enc_values_supported,
|
30
31
|
:id_token_signing_alg_values_supported,
|
31
32
|
:id_token_encryption_alg_values_supported,
|
32
33
|
:id_token_encryption_enc_values_supported,
|
33
34
|
:request_object_signing_alg_values_supported,
|
34
35
|
:request_object_encryption_alg_values_supported,
|
35
36
|
:request_object_encryption_enc_values_supported,
|
36
|
-
:
|
37
|
+
:token_endpoint_auth_methods_supported,
|
37
38
|
:token_endpoint_auth_signing_alg_values_supported
|
38
39
|
)
|
40
|
+
[
|
41
|
+
:userinfo_endpoint,
|
42
|
+
:userinfo_signing_alg_values_supported,
|
43
|
+
:userinfo_encryption_alg_values_supported,
|
44
|
+
:userinfo_encryption_enc_values_supported
|
45
|
+
].each do |userinfo_attribute|
|
46
|
+
user_info_attribute = userinfo_attribute.to_s.sub('userinfo', 'user_info').to_sym
|
47
|
+
alias_method user_info_attribute, userinfo_attribute
|
48
|
+
alias_method :"#{user_info_attribute}=", userinfo_attribute
|
49
|
+
end
|
39
50
|
|
40
51
|
def initialize(hash)
|
41
52
|
optional_attributes.each do |key|
|
42
53
|
self.send "#{key}=", hash[key]
|
43
54
|
end
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
55
|
+
self.userinfo_endpoint ||= hash[:user_info_endpoint]
|
56
|
+
self.userinfo_signing_alg_values_supported ||= hash[:user_info_signing_alg_values_supported]
|
57
|
+
self.userinfo_encryption_alg_values_supported ||= hash[:user_info_encryption_alg_values_supported]
|
58
|
+
self.userinfo_encryption_enc_values_supported ||= hash[:user_info_encryption_enc_values_supported]
|
59
|
+
self.version ||= '3.0'
|
49
60
|
@raw = hash
|
50
61
|
end
|
51
62
|
|
@@ -55,10 +66,6 @@ module OpenIDConnect
|
|
55
66
|
_attr_ => self.send(_attr_)
|
56
67
|
)
|
57
68
|
end
|
58
|
-
hash[:userinfo_endpoint] = hash.delete(:user_info_endpoint)
|
59
|
-
hash[:userinfo_signing_alg_values_supported] = hash.delete(:user_info_signing_alg_values_supported)
|
60
|
-
hash[:userinfo_encryption_alg_values_supported] = hash.delete(:user_info_encryption_alg_values_supported)
|
61
|
-
hash[:userinfo_encryption_enc_values_supported] = hash.delete(:user_info_encryption_enc_values_supported)
|
62
69
|
hash.delete_if do |key, value|
|
63
70
|
value.nil?
|
64
71
|
end
|
@@ -1,10 +1,13 @@
|
|
1
1
|
module OpenIDConnect
|
2
2
|
class RequestObject < ConnectObject
|
3
|
-
|
3
|
+
include JWTnizable
|
4
|
+
|
5
|
+
attr_optional :client_id, :response_type, :redirect_uri, :scope, :state, :nonce, :display, :prompt, :userinfo, :id_token
|
6
|
+
alias_method :user_info, :userinfo
|
4
7
|
validate :require_at_least_one_attributes
|
5
8
|
|
6
9
|
def initialize(attributes = {})
|
7
|
-
attributes[:
|
10
|
+
attributes[:userinfo] ||= attributes[:user_info]
|
8
11
|
super attributes
|
9
12
|
end
|
10
13
|
|
@@ -12,20 +15,16 @@ module OpenIDConnect
|
|
12
15
|
@id_token = IdToken.new(attributes) if attributes.present?
|
13
16
|
end
|
14
17
|
|
15
|
-
def
|
16
|
-
@
|
18
|
+
def userinfo=(attributes = {})
|
19
|
+
@userinfo = UserInfo.new(attributes) if attributes.present?
|
17
20
|
end
|
21
|
+
alias_method :user_info=, :userinfo=
|
18
22
|
|
19
|
-
def
|
20
|
-
hash =
|
21
|
-
if hash.include?(:user_info)
|
22
|
-
hash[:userinfo] = hash.delete(:user_info)
|
23
|
-
end
|
23
|
+
def as_json_with_mixed_keys(options = {})
|
24
|
+
hash = as_json_without_mixed_keys options
|
24
25
|
hash.with_indifferent_access
|
25
26
|
end
|
26
|
-
alias_method_chain :as_json, :
|
27
|
-
|
28
|
-
include JWTnizable
|
27
|
+
alias_method_chain :as_json, :mixed_keys
|
29
28
|
|
30
29
|
class << self
|
31
30
|
def decode(jwt_string, key = nil)
|
@@ -5,13 +5,15 @@ module OpenIDConnect
|
|
5
5
|
class IdToken < ConnectObject
|
6
6
|
class InvalidToken < Exception; end
|
7
7
|
|
8
|
-
attr_required :iss, :
|
9
|
-
attr_optional :acr, :auth_time, :nonce, :
|
8
|
+
attr_required :iss, :sub, :aud, :exp, :iat
|
9
|
+
attr_optional :acr, :auth_time, :nonce, :sub_jwk, :at_hash, :c_hash
|
10
10
|
attr_accessor :access_token, :code
|
11
|
+
alias_method :subject, :sub
|
12
|
+
alias_method :subject=, :sub=
|
11
13
|
|
12
14
|
def initialize(attributes = {})
|
13
15
|
super
|
14
|
-
(all_attributes - [:exp, :iat, :auth_time, :
|
16
|
+
(all_attributes - [:exp, :iat, :auth_time, :sub_jwk]).each do |key|
|
15
17
|
self.send "#{key}=", self.send(key).try(:to_s)
|
16
18
|
end
|
17
19
|
end
|
@@ -61,25 +63,25 @@ module OpenIDConnect
|
|
61
63
|
|
62
64
|
def decode_self_issued(jwt_string)
|
63
65
|
jwt = JSON::JWT.decode jwt_string, :skip_verification
|
64
|
-
jwk = jwt[:
|
65
|
-
raise InvalidToken.new('Missing
|
66
|
-
raise InvalidToken.new('Invalid
|
66
|
+
jwk = jwt[:sub_jwk]
|
67
|
+
raise InvalidToken.new('Missing sub_jwk') if jwk.blank?
|
68
|
+
raise InvalidToken.new('Invalid subject') unless jwt[:sub] == self_issued_subject(jwk)
|
67
69
|
public_key = JSON::JWK.decode jwk
|
68
70
|
jwt = JSON::JWT.decode jwt_string, public_key
|
69
71
|
new jwt
|
70
72
|
end
|
71
73
|
|
72
74
|
def self_issued(attributes = {})
|
73
|
-
attributes[:
|
75
|
+
attributes[:sub_jwk] ||= JSON::JWK.new attributes.delete(:public_key)
|
74
76
|
_attributes_ = {
|
75
|
-
iss:
|
76
|
-
|
77
|
+
iss: 'https://self-issued.me',
|
78
|
+
sub: self_issued_subject(attributes[:sub_jwk])
|
77
79
|
}.merge(attributes)
|
78
80
|
new _attributes_
|
79
81
|
end
|
80
82
|
|
81
|
-
def
|
82
|
-
|
83
|
+
def self_issued_subject(jwk)
|
84
|
+
subject_base_string = case jwk[:alg].to_s
|
83
85
|
when 'RSA'
|
84
86
|
[jwk[:n], jwk[:e]].join
|
85
87
|
when 'EC'
|
@@ -88,7 +90,7 @@ module OpenIDConnect
|
|
88
90
|
# Shouldn't reach here. All unknown algorithm error should occurs when decoding JWK
|
89
91
|
raise InvalidToken.new('Unknown Algorithm')
|
90
92
|
end
|
91
|
-
UrlSafeBase64.encode64 OpenSSL::Digest::SHA256.digest(
|
93
|
+
UrlSafeBase64.encode64 OpenSSL::Digest::SHA256.digest(subject_base_string)
|
92
94
|
end
|
93
95
|
end
|
94
96
|
end
|
@@ -3,7 +3,7 @@ module OpenIDConnect
|
|
3
3
|
module UserInfo
|
4
4
|
class OpenID < ConnectObject
|
5
5
|
attr_optional(
|
6
|
-
:
|
6
|
+
:sub,
|
7
7
|
:name,
|
8
8
|
:given_name,
|
9
9
|
:family_name,
|
@@ -23,6 +23,8 @@ module OpenIDConnect
|
|
23
23
|
:address,
|
24
24
|
:updated_time
|
25
25
|
)
|
26
|
+
alias_method :subject, :sub
|
27
|
+
alias_method :subject=, :sub=
|
26
28
|
|
27
29
|
validates :email_verified, inclusion: {in: [true, false]}, allow_nil: true
|
28
30
|
validates :gender, inclusion: {in: ['male', 'female']}, allow_nil: true
|
@@ -7,6 +7,7 @@
|
|
7
7
|
"registration_endpoint": "https://connect-op.heroku.com/connect/client",
|
8
8
|
"scopes_supported": ["openid", "profile", "email", "address"],
|
9
9
|
"response_types_supported": ["code", "token", "id_token", "code token", "code id_token", "id_token token"],
|
10
|
-
"
|
10
|
+
"subject_types_supported": ["public", "pairwise"],
|
11
|
+
"claims_supported": ["sub", "iss", "name", "email"],
|
11
12
|
"x509_url": "https://connect-op.heroku.com/cert.pem"
|
12
13
|
}
|
@@ -5,7 +5,7 @@ describe OpenIDConnect::Client::Registrar do
|
|
5
5
|
let(:attributes) { minimum_attributes }
|
6
6
|
let(:minimum_attributes) do
|
7
7
|
{
|
8
|
-
|
8
|
+
operation: :client_register
|
9
9
|
}
|
10
10
|
end
|
11
11
|
let(:instance) { OpenIDConnect::Client::Registrar.new(endpoint, attributes) }
|
@@ -13,18 +13,18 @@ describe OpenIDConnect::Client::Registrar do
|
|
13
13
|
|
14
14
|
context 'when endpoint given' do
|
15
15
|
context 'when attributes given' do
|
16
|
-
context 'when
|
16
|
+
context 'when operation=client_register' do
|
17
17
|
let(:attributes) do
|
18
18
|
minimum_attributes
|
19
19
|
end
|
20
20
|
it { should be_valid }
|
21
21
|
end
|
22
22
|
|
23
|
-
context 'when
|
23
|
+
context 'when operation=client_update' do
|
24
24
|
context 'when client_id given' do
|
25
25
|
let(:attributes) do
|
26
26
|
{
|
27
|
-
|
27
|
+
operation: :client_update,
|
28
28
|
client_id: 'client.example.com'
|
29
29
|
}
|
30
30
|
end
|
@@ -34,7 +34,7 @@ describe OpenIDConnect::Client::Registrar do
|
|
34
34
|
context 'otherwise' do
|
35
35
|
let(:attributes) do
|
36
36
|
{
|
37
|
-
|
37
|
+
operation: :client_update
|
38
38
|
}
|
39
39
|
end
|
40
40
|
it { should_not be_valid }
|
@@ -44,7 +44,7 @@ describe OpenIDConnect::Client::Registrar do
|
|
44
44
|
context 'otherwise' do
|
45
45
|
let(:attributes) do
|
46
46
|
{
|
47
|
-
|
47
|
+
operation: :invalid_operation
|
48
48
|
}
|
49
49
|
end
|
50
50
|
it { should_not be_valid }
|
@@ -209,7 +209,7 @@ describe OpenIDConnect::Client::Registrar do
|
|
209
209
|
end
|
210
210
|
its(:as_json) do
|
211
211
|
should == {
|
212
|
-
|
212
|
+
operation: 'client_register',
|
213
213
|
redirect_uris: 'https://client1.example.com/callback https://client2.example.com/callback'
|
214
214
|
}
|
215
215
|
end
|
@@ -218,7 +218,7 @@ describe OpenIDConnect::Client::Registrar do
|
|
218
218
|
context 'otherwise' do
|
219
219
|
let(:attributes) do
|
220
220
|
{
|
221
|
-
|
221
|
+
operation: :client_update
|
222
222
|
}
|
223
223
|
end
|
224
224
|
it do
|
@@ -229,16 +229,16 @@ describe OpenIDConnect::Client::Registrar do
|
|
229
229
|
end
|
230
230
|
end
|
231
231
|
|
232
|
-
describe '#
|
232
|
+
describe '#register!' do
|
233
233
|
let(:attributes) do
|
234
234
|
{}
|
235
235
|
end
|
236
236
|
|
237
237
|
it 'should return OpenIDConnect::Client' do
|
238
238
|
mock_json :post, endpoint, 'client/registered', params: {
|
239
|
-
|
239
|
+
operation: 'client_register'
|
240
240
|
} do
|
241
|
-
client = instance.
|
241
|
+
client = instance.register!
|
242
242
|
client.should be_instance_of OpenIDConnect::Client
|
243
243
|
client.identifier.should == 'client.example.com'
|
244
244
|
client.secret.should == 'client_secret'
|
@@ -249,10 +249,10 @@ describe OpenIDConnect::Client::Registrar do
|
|
249
249
|
context 'when failed' do
|
250
250
|
it 'should raise OpenIDConnect::Client::Registrar::RegistrationFailed' do
|
251
251
|
mock_json :post, endpoint, 'errors/unknown', params: {
|
252
|
-
|
252
|
+
operation: 'client_register'
|
253
253
|
}, status: 400 do
|
254
254
|
expect do
|
255
|
-
instance.
|
255
|
+
instance.register!
|
256
256
|
end.to raise_error OpenIDConnect::Client::Registrar::RegistrationFailed
|
257
257
|
end
|
258
258
|
end
|
@@ -269,12 +269,12 @@ describe OpenIDConnect::Client::Registrar do
|
|
269
269
|
|
270
270
|
it 'should return OpenIDConnect::Client' do
|
271
271
|
mock_json :post, endpoint, 'client/updated', params: {
|
272
|
-
|
272
|
+
operation: 'client_update',
|
273
273
|
client_id: 'client.example.com',
|
274
274
|
client_secret: 'client_secret',
|
275
|
-
|
275
|
+
client_name: 'New Name'
|
276
276
|
} do
|
277
|
-
instance.
|
277
|
+
instance.client_name = 'New Name'
|
278
278
|
client = instance.update!
|
279
279
|
client.should be_instance_of OpenIDConnect::Client
|
280
280
|
client.identifier.should == 'client.example.com'
|
@@ -284,7 +284,7 @@ describe OpenIDConnect::Client::Registrar do
|
|
284
284
|
context 'when failed' do
|
285
285
|
it 'should raise OpenIDConnect::Client::Registrar::RegistrationFailed' do
|
286
286
|
mock_json :post, endpoint, 'errors/unknown', params: {
|
287
|
-
|
287
|
+
operation: 'client_update',
|
288
288
|
client_id: 'client.example.com',
|
289
289
|
client_secret: 'client_secret'
|
290
290
|
}, status: 400 do
|
@@ -306,7 +306,7 @@ describe OpenIDConnect::Client::Registrar do
|
|
306
306
|
|
307
307
|
it 'should return OpenIDConnect::Client' do
|
308
308
|
mock_json :post, endpoint, 'client/rotated', params: {
|
309
|
-
|
309
|
+
operation: 'rotate_secret',
|
310
310
|
client_id: 'client.example.com',
|
311
311
|
client_secret: 'client_secret'
|
312
312
|
} do
|
@@ -331,7 +331,7 @@ describe OpenIDConnect::Client::Registrar do
|
|
331
331
|
context 'otherwise' do
|
332
332
|
let(:attributes) do
|
333
333
|
{
|
334
|
-
|
334
|
+
operation: :client_update
|
335
335
|
}
|
336
336
|
end
|
337
337
|
it do
|
@@ -21,8 +21,9 @@ describe OpenIDConnect::Discovery::Provider::Config do
|
|
21
21
|
config.registration_endpoint.should == 'https://connect-op.heroku.com/connect/client'
|
22
22
|
config.scopes_supported.should == ["openid", "profile", "email", "address"]
|
23
23
|
config.response_types_supported.should == ["code", "token", "id_token", "code token", "code id_token", "id_token token"]
|
24
|
-
config.
|
25
|
-
config.
|
24
|
+
config.acr_values_supported.should be_nil
|
25
|
+
config.subject_types_supported.should == ["public", "pairwise"]
|
26
|
+
config.claims_supported.should == ["sub", "iss", "name", "email"]
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
@@ -15,12 +15,6 @@ describe OpenIDConnect::RequestObject do
|
|
15
15
|
nonce: 'nonce1234',
|
16
16
|
display: 'touch',
|
17
17
|
prompt: 'none',
|
18
|
-
userinfo: {
|
19
|
-
claims: {
|
20
|
-
name: :required,
|
21
|
-
email: :optional
|
22
|
-
}
|
23
|
-
},
|
24
18
|
id_token: {
|
25
19
|
max_age: 10,
|
26
20
|
claims: {
|
@@ -28,11 +22,17 @@ describe OpenIDConnect::RequestObject do
|
|
28
22
|
values: ['2', '3', '4']
|
29
23
|
}
|
30
24
|
}
|
25
|
+
},
|
26
|
+
userinfo: {
|
27
|
+
claims: {
|
28
|
+
name: :required,
|
29
|
+
email: :optional
|
30
|
+
}
|
31
31
|
}
|
32
32
|
}
|
33
33
|
end
|
34
34
|
let(:jwtnized) do
|
35
|
-
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
|
35
|
+
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjbGllbnRfaWQiOiJjbGllbnRfaWQiLCJyZXNwb25zZV90eXBlIjoidG9rZW4gaWRfdG9rZW4iLCJyZWRpcmVjdF91cmkiOiJodHRwczovL2NsaWVudC5leGFtcGxlLmNvbSIsInNjb3BlIjoib3BlbmlkIGVtYWlsIiwic3RhdGUiOiJzdGF0ZTEyMzQiLCJub25jZSI6Im5vbmNlMTIzNCIsImRpc3BsYXkiOiJ0b3VjaCIsInByb21wdCI6Im5vbmUiLCJ1c2VyaW5mbyI6eyJjbGFpbXMiOnsibmFtZSI6eyJlc3NlbnRpYWwiOnRydWV9LCJlbWFpbCI6eyJlc3NlbnRpYWwiOmZhbHNlfX19LCJpZF90b2tlbiI6eyJjbGFpbXMiOnsiYWNyIjp7InZhbHVlcyI6WyIyIiwiMyIsIjQiXX19LCJtYXhfYWdlIjoxMH19.yOc76jnkDusf5ZUzI5Gq7vnteTeOVUXd2Fr1EBZFNYU'
|
36
36
|
end
|
37
37
|
let(:jsonized) do
|
38
38
|
{
|
@@ -9,7 +9,7 @@ describe OpenIDConnect::ResponseObject::IdToken do
|
|
9
9
|
let :required_attributes do
|
10
10
|
{
|
11
11
|
iss: 'https://server.example.com',
|
12
|
-
|
12
|
+
sub: 'user_id',
|
13
13
|
aud: 'client_id',
|
14
14
|
exp: ext,
|
15
15
|
iat: iat
|
@@ -18,8 +18,8 @@ describe OpenIDConnect::ResponseObject::IdToken do
|
|
18
18
|
|
19
19
|
describe 'attributes' do
|
20
20
|
subject { klass }
|
21
|
-
its(:required_attributes) { should == [:iss, :
|
22
|
-
its(:optional_attributes) { should == [:acr, :auth_time, :nonce, :
|
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] }
|
23
23
|
end
|
24
24
|
|
25
25
|
describe '#verify!' do
|
@@ -217,7 +217,7 @@ describe OpenIDConnect::ResponseObject::IdToken do
|
|
217
217
|
subject { klass.decode id_token.to_jwt(private_key), public_key }
|
218
218
|
let(:attributes) { required_attributes }
|
219
219
|
it { should be_a klass }
|
220
|
-
[:iss, :
|
220
|
+
[:iss, :sub, :aud].each do |key|
|
221
221
|
its(key) { should == attributes[key] }
|
222
222
|
end
|
223
223
|
its(:exp) { should == attributes[:exp].to_i }
|
@@ -225,7 +225,7 @@ describe OpenIDConnect::ResponseObject::IdToken do
|
|
225
225
|
context 'when self-issued' do
|
226
226
|
context 'when valid' do
|
227
227
|
let(:self_issued) do
|
228
|
-
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.
|
228
|
+
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL3NlbGYtaXNzdWVkLm1lIiwic3ViIjoiUFdFYXFfVnlUd1hTSFR4QVlSZHdWTjNMN2s0UnNxOVBwaTZ4WHZ6ZGZWTSIsImF1ZCI6InRhcGlkLnRhcGlkZW50aXR5LmNvbSIsImV4cCI6MTM2MjI3OTkwMCwiaWF0IjoxMzYyMjc2MzAwLCJzdWJfandrIjp7ImFsZyI6IlJTQSIsIm4iOiJ5R21SUm5qSkk2VWhXYUtYcUJxa0RodDVQa0FPdDNqV2Y0SUxIdUlKZHJHR3h1ajBhcDIzLXlxaS16N29jZmF3dnlNbkRfakRpY0JjRTFtVHduZ2ZLRURMdmp5ZWw4U3VhZlZJWTR4ZDVDcG42Nlp4U2pocE1yTWZtMF9palZtdkQ0OTZHZzZSYUR4cHA4OEVqcUlaZUtyZEtqd2lOeTRGZ0dkVnZPQURXWG85R0xLenBOdlc2MGU3MkdrRGFkUVJncEhGNjNVaE9zaVltYmwxRVRMaVhLMGpUdldDdEZVdUlfT2lTN3hIUmU0X3FSaWxRc240cGlHTy1lNzJ2azRpaFlPaldoRXNpcnU2X0JtSC03YWs2Qk9lY3pUYTFVOFZyQzY1ZkRabzRxeG9uRWVoeVpVVnItSmxXMFVvbFVTS1dKOE1OMGRBV1VaeTFBZUxtRzliZlEiLCJlIjoiQVFBQiJ9fQ.obpb9tshLoZG6O32w4nB4I3nBtR_2mscVeNuPWZAGIwq9SqpiNF24KrGrhgbJMzRndafXbOdiiTFjq15BDwoSUrRF2H2EQXm1_lZxhw66JK4get7zEihtmsljGxB03LRlej-ec6baAKJxCBZdJ7SIantjgyt_WbAY27ImeryD7Wi9VKtgEzX2cFbU8u5VwxpisDfosp7fpp0_jdAdk948eJnercM-6t0a3UhLoLaW1RWZSbzXzef9aDuMezsnSrwafjYuF6dzUF7uAEdsYAzMeISch2_Gl4Twbrovmmqj50IKIctkLxQBTI1_v0oU63_a4jLami1cux8XTEfgPEPmg'
|
229
229
|
end
|
230
230
|
|
231
231
|
context 'when key == :self_issued' do
|
@@ -245,27 +245,27 @@ describe OpenIDConnect::ResponseObject::IdToken do
|
|
245
245
|
end
|
246
246
|
end
|
247
247
|
|
248
|
-
context 'when invalid
|
248
|
+
context 'when invalid subject' do
|
249
249
|
let(:self_issued) do
|
250
|
-
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.
|
250
|
+
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJkZXZpY2VfdG9rZW4iOiI2NjYxNmI2NTJkNjQ2NTc2Njk2MzY1MmQ3NDZmNmI2NTZlIiwiaXNzIjoiaHR0cHM6Ly9zZWxmLWlzc3VlZC5tZSIsInN1YiI6IlBXRWFxX1Z5VHdYU0hUeEFZUmR3Vk4zTDdrNFJzcTlQcGk2eFh2emRmVk1pbnZhbGlkIiwiYXVkIjoidGFwaWQudGFwaWRlbnRpdHkuY29tIiwiZXhwIjoxMzYyMjgwMDQxLCJpYXQiOjEzNjIyNzY0NDEsInN1Yl9qd2siOnsiYWxnIjoiUlNBIiwibiI6InlHbVJSbmpKSTZVaFdhS1hxQnFrRGh0NVBrQU90M2pXZjRJTEh1SUpkckdHeHVqMGFwMjMteXFpLXo3b2NmYXd2eU1uRF9qRGljQmNFMW1Ud25nZktFREx2anllbDhTdWFmVklZNHhkNUNwbjY2WnhTamhwTXJNZm0wX2lqVm12RDQ5NkdnNlJhRHhwcDg4RWpxSVplS3JkS2p3aU55NEZnR2RWdk9BRFdYbzlHTEt6cE52VzYwZTcyR2tEYWRRUmdwSEY2M1VoT3NpWW1ibDFFVExpWEswalR2V0N0RlV1SV9PaVM3eEhSZTRfcVJpbFFzbjRwaUdPLWU3MnZrNGloWU9qV2hFc2lydTZfQm1ILTdhazZCT2VjelRhMVU4VnJDNjVmRFpvNHF4b25FZWh5WlVWci1KbFcwVW9sVVNLV0o4TU4wZEFXVVp5MUFlTG1HOWJmUSIsImUiOiJBUUFCIn19.K8NpQ1r89v9KFcrAU19-qTEtUv94gTJp25xwYwKPttkMOduGMIBn1lCTUsWhUC8NDc0lJrIq-MAa3Eav6wlW9HkX4Gw7vD-fwx6bijm_0LnxLcK2PwMPeeAaeztEOj6WNnUlipZAkOjYhFWG_4gK4sbnoXv80LSV3dHf0mwDEp0vWJ5rba24YfyFb_CoGfeluaHVQiCWTNFa4rh5ohCb1oC4IAZd607KNryLBbjGdyRgIgeIBtph_rx4Jf2tYhBs1_Y32KQMgKHy7QBJHD1hr2HEAu_pCXirwpNFcBCV7K5vUYntYSjdrKfvEzeW0Jxjm1AGgMZr_NsGwNS0bMYoUA'
|
251
251
|
end
|
252
252
|
|
253
253
|
it do
|
254
254
|
expect do
|
255
255
|
klass.decode self_issued, :self_issued
|
256
|
-
end.to raise_error OpenIDConnect::ResponseObject::IdToken::InvalidToken, 'Invalid
|
256
|
+
end.to raise_error OpenIDConnect::ResponseObject::IdToken::InvalidToken, 'Invalid subject'
|
257
257
|
end
|
258
258
|
end
|
259
259
|
|
260
|
-
context 'when no
|
260
|
+
context 'when no sub_jwk' do
|
261
261
|
let(:self_issued) do
|
262
|
-
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.
|
262
|
+
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJkZXZpY2VfdG9rZW4iOiI2NjYxNmI2NTJkNjQ2NTc2Njk2MzY1MmQ3NDZmNmI2NTZlIiwiaXNzIjoiaHR0cHM6Ly9zZWxmLWlzc3VlZC5tZSIsInN1YiI6IlBXRWFxX1Z5VHdYU0hUeEFZUmR3Vk4zTDdrNFJzcTlQcGk2eFh2emRmVk0iLCJhdWQiOiJ0YXBpZC50YXBpZGVudGl0eS5jb20iLCJleHAiOjEzNjIyODAxNDQsImlhdCI6MTM2MjI3NjU0NH0.HtkguN4xOzJ-yh_kd2JCmG6fgDEiVY5VCgTWUD9l8YOgHjTT7LRZC3b1sNDgkdwBteX3eQIQOVxaYWp4-ftczaIlrznB0jxldqdEdB1Tr591YsiDcyOqmemo1ZYzOKhe_q1l68bdKKeHLc83BzlsJpS659uFDuixvF7G_HIJpCdwckX7x6H3KK73hCLzoYCOVgr_lkFRVVHHAJXzxiUuERLD7JIvg5jCbgmqxArP-jYBdbscHHx8i-UP3WYFBEORBM2rXJuJzGvk4sLhZ4NVGBWyr0DJlE-aWKTyeg-_-4kLPd3d68-k3nLJ82iCwcap-BU_5otSmXufN3_ffq_tTw'
|
263
263
|
end
|
264
264
|
|
265
265
|
it do
|
266
266
|
expect do
|
267
267
|
klass.decode self_issued, :self_issued
|
268
|
-
end.to raise_error OpenIDConnect::ResponseObject::IdToken::InvalidToken, 'Missing
|
268
|
+
end.to raise_error OpenIDConnect::ResponseObject::IdToken::InvalidToken, 'Missing sub_jwk'
|
269
269
|
end
|
270
270
|
end
|
271
271
|
end
|
@@ -273,7 +273,7 @@ describe OpenIDConnect::ResponseObject::IdToken do
|
|
273
273
|
|
274
274
|
describe '.self_issued' do
|
275
275
|
subject { self_issued }
|
276
|
-
let(:
|
276
|
+
let(:sub_jwk) { JSON::JWK.new(public_key) }
|
277
277
|
let(:self_issued) do
|
278
278
|
klass.self_issued(
|
279
279
|
public_key: public_key,
|
@@ -283,19 +283,19 @@ describe OpenIDConnect::ResponseObject::IdToken do
|
|
283
283
|
)
|
284
284
|
end
|
285
285
|
|
286
|
-
[:iss, :
|
286
|
+
[:iss, :sub, :aud, :exp, :iat, :sub_jwk].each do |attribute|
|
287
287
|
its(attribute) { should be_present }
|
288
288
|
end
|
289
289
|
its(:iss) { should == 'https://self-issued.me' }
|
290
|
-
its(:
|
291
|
-
its(:
|
290
|
+
its(:sub_jwk) { should == sub_jwk}
|
291
|
+
its(:subject) { should == OpenIDConnect::ResponseObject::IdToken.self_issued_subject(sub_jwk) }
|
292
292
|
end
|
293
293
|
|
294
|
-
describe '.
|
294
|
+
describe '.self_issued_subject' do
|
295
295
|
context 'when RSA key given' do
|
296
296
|
let(:jwk) { JSON::JWK.new(public_key) }
|
297
297
|
it do
|
298
|
-
user_id = klass.
|
298
|
+
user_id = klass.self_issued_subject jwk
|
299
299
|
user_id.should == UrlSafeBase64.encode64(
|
300
300
|
OpenSSL::Digest::SHA256.digest([jwk[:n], jwk[:e]].join)
|
301
301
|
)
|
@@ -306,7 +306,7 @@ describe OpenIDConnect::ResponseObject::IdToken do
|
|
306
306
|
let(:jwk) { JSON::JWK.new(ec_public_key) }
|
307
307
|
it do
|
308
308
|
expect do
|
309
|
-
|
309
|
+
klass.self_issued_subject jwk
|
310
310
|
end.to raise_error NotImplementedError
|
311
311
|
end
|
312
312
|
end
|
@@ -320,7 +320,7 @@ describe OpenIDConnect::ResponseObject::IdToken do
|
|
320
320
|
|
321
321
|
it do
|
322
322
|
expect do
|
323
|
-
|
323
|
+
klass.self_issued_subject jwk
|
324
324
|
end.to raise_error OpenIDConnect::ResponseObject::IdToken::InvalidToken
|
325
325
|
end
|
326
326
|
end
|
@@ -10,7 +10,7 @@ describe OpenIDConnect::ResponseObject::UserInfo::OpenID do
|
|
10
10
|
its(:required_attributes) { should == [] }
|
11
11
|
its(:optional_attributes) do
|
12
12
|
should == [
|
13
|
-
:
|
13
|
+
:sub,
|
14
14
|
:name,
|
15
15
|
:given_name,
|
16
16
|
:family_name,
|
@@ -108,13 +108,13 @@ describe OpenIDConnect::ResponseObject::UserInfo::OpenID do
|
|
108
108
|
describe '#to_json' do
|
109
109
|
let :attributes do
|
110
110
|
{
|
111
|
-
|
111
|
+
sub: 'nov.matake#12345',
|
112
112
|
address: {
|
113
113
|
formatted: 'Tokyo, Japan'
|
114
114
|
}
|
115
115
|
}
|
116
116
|
end
|
117
|
-
its(:to_json) { should include '"
|
117
|
+
its(:to_json) { should include '"sub":"nov.matake#12345"'}
|
118
118
|
its(:to_json) { should include '"address":{"formatted":"Tokyo, Japan"}'}
|
119
119
|
end
|
120
120
|
end
|
@@ -10,7 +10,7 @@ describe Rack::OAuth2::Server::Authorize::Extension::CodeAndIdTokenAndToken do
|
|
10
10
|
let :id_token do
|
11
11
|
OpenIDConnect::ResponseObject::IdToken.new(
|
12
12
|
iss: 'https://server.example.com',
|
13
|
-
|
13
|
+
sub: 'user_id',
|
14
14
|
aud: 'client_id',
|
15
15
|
nonce: 'nonce',
|
16
16
|
exp: 1313424327,
|
@@ -9,7 +9,7 @@ describe Rack::OAuth2::Server::Authorize::Extension::CodeAndIdToken do
|
|
9
9
|
let :id_token do
|
10
10
|
OpenIDConnect::ResponseObject::IdToken.new(
|
11
11
|
iss: 'https://server.example.com',
|
12
|
-
|
12
|
+
sub: 'user_id',
|
13
13
|
aud: 'client_id',
|
14
14
|
nonce: 'nonce',
|
15
15
|
exp: 1313424327,
|
@@ -9,7 +9,7 @@ describe Rack::OAuth2::Server::Authorize::Extension::IdTokenAndToken do
|
|
9
9
|
let :id_token do
|
10
10
|
OpenIDConnect::ResponseObject::IdToken.new(
|
11
11
|
iss: 'https://server.example.com',
|
12
|
-
|
12
|
+
sub: 'user_id',
|
13
13
|
aud: 'client_id',
|
14
14
|
nonce: 'nonce',
|
15
15
|
exp: 1313424327,
|
@@ -8,7 +8,7 @@ describe Rack::OAuth2::Server::Authorize::Extension::IdToken do
|
|
8
8
|
let :id_token do
|
9
9
|
OpenIDConnect::ResponseObject::IdToken.new(
|
10
10
|
iss: 'https://server.example.com',
|
11
|
-
|
11
|
+
sub: 'user_id',
|
12
12
|
aud: 'client_id',
|
13
13
|
nonce: 'nonce',
|
14
14
|
exp: 1313424327,
|
@@ -14,7 +14,7 @@ describe Rack::OAuth2::Server::Token::AuthorizationCode do
|
|
14
14
|
let :id_token do
|
15
15
|
OpenIDConnect::ResponseObject::IdToken.new(
|
16
16
|
iss: 'https://server.example.com',
|
17
|
-
|
17
|
+
sub: 'user_id',
|
18
18
|
aud: 'client_id',
|
19
19
|
exp: 1313424327,
|
20
20
|
iat: 1313420327,
|
@@ -13,7 +13,7 @@ describe Rack::OAuth2::Server::Token::RefreshToken do
|
|
13
13
|
let :id_token do
|
14
14
|
OpenIDConnect::ResponseObject::IdToken.new(
|
15
15
|
iss: 'https://server.example.com',
|
16
|
-
|
16
|
+
sub: 'user_id',
|
17
17
|
aud: 'client_id',
|
18
18
|
exp: 1313424327,
|
19
19
|
iat: 1313420327,
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openid_connect
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nov matake
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-03-
|
11
|
+
date: 2013-03-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|