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