openid_connect 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -2
- data/Gemfile.lock +1 -2
- data/VERSION +1 -1
- data/lib/openid_connect/access_token.rb +0 -8
- data/lib/openid_connect/client.rb +1 -6
- data/lib/openid_connect/client/registrar.rb +19 -7
- data/lib/openid_connect/discovery/principal.rb +1 -4
- data/lib/openid_connect/discovery/provider/config/response.rb +0 -1
- data/lib/openid_connect/response_object/id_token.rb +3 -11
- data/spec/mock_response/client/registered.json +1 -1
- data/spec/mock_response/client/rotated.json +5 -0
- data/spec/mock_response/client/updated.json +1 -3
- data/spec/mock_response/discovery/config.json +0 -1
- data/spec/openid_connect/access_token_spec.rb +0 -14
- data/spec/openid_connect/client/registrar_spec.rb +28 -5
- data/spec/openid_connect/client_spec.rb +1 -2
- data/spec/openid_connect/discovery/principal_spec.rb +1 -3
- data/spec/openid_connect/discovery/provider/config_spec.rb +0 -1
- data/spec/openid_connect/response_object/id_token_spec.rb +7 -32
- metadata +3 -4
- data/lib/openid_connect/discovery/principal/xri.rb +0 -15
- data/spec/openid_connect/discovery/principal/xri_spec.rb +0 -5
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
openid_connect (0.2.
|
4
|
+
openid_connect (0.2.1)
|
5
5
|
activemodel (>= 3)
|
6
6
|
attr_required (>= 0.0.5)
|
7
7
|
json (>= 1.4.3)
|
@@ -38,7 +38,6 @@ GEM
|
|
38
38
|
jruby-openssl (0.7.7)
|
39
39
|
bouncy-castle-java (>= 1.5.0146.1)
|
40
40
|
json (1.7.3)
|
41
|
-
json (1.7.3-java)
|
42
41
|
json-jwt (0.0.7)
|
43
42
|
activesupport (>= 2.3)
|
44
43
|
i18n
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.2
|
@@ -15,14 +15,6 @@ module OpenIDConnect
|
|
15
15
|
ResponseObject::UserInfo::OpenID.new hash
|
16
16
|
end
|
17
17
|
|
18
|
-
def id_token!
|
19
|
-
client.check_id_uri
|
20
|
-
hash = resource_request do
|
21
|
-
get client.check_id_uri
|
22
|
-
end
|
23
|
-
ResponseObject::IdToken.new hash
|
24
|
-
end
|
25
|
-
|
26
18
|
private
|
27
19
|
|
28
20
|
def resource_request
|
@@ -1,11 +1,10 @@
|
|
1
1
|
module OpenIDConnect
|
2
2
|
class Client < Rack::OAuth2::Client
|
3
|
-
attr_optional :
|
3
|
+
attr_optional :user_info_endpoint, :expires_in
|
4
4
|
|
5
5
|
def initialize(attributes = {})
|
6
6
|
super
|
7
7
|
@user_info_endpoint ||= '/user_info'
|
8
|
-
@check_id_endpoint ||= '/id_token'
|
9
8
|
end
|
10
9
|
|
11
10
|
def authorization_uri(params = {})
|
@@ -14,10 +13,6 @@ module OpenIDConnect
|
|
14
13
|
super
|
15
14
|
end
|
16
15
|
|
17
|
-
def check_id_uri
|
18
|
-
absolute_uri_for check_id_endpoint
|
19
|
-
end
|
20
|
-
|
21
16
|
def user_info_uri
|
22
17
|
absolute_uri_for user_info_endpoint
|
23
18
|
end
|
@@ -22,14 +22,21 @@ module OpenIDConnect
|
|
22
22
|
:sector_identifier_url,
|
23
23
|
:user_id_type,
|
24
24
|
:require_signed_request_object,
|
25
|
+
:userinfo_signed_response_alg,
|
26
|
+
:userinfo_encrypted_response_alg,
|
27
|
+
:userinfo_encrypted_response_enc,
|
28
|
+
:userinfo_encrypted_response_int,
|
29
|
+
:id_token_signed_response_alg,
|
30
|
+
:id_token_encrypted_response_alg,
|
31
|
+
:id_token_encrypted_response_enc,
|
32
|
+
:id_token_encrypted_response_int,
|
33
|
+
:default_max_age,
|
34
|
+
:require_auth_time,
|
35
|
+
:default_acr
|
25
36
|
]
|
26
37
|
plurar_attributes = [
|
27
38
|
:contacts,
|
28
|
-
:redirect_uris
|
29
|
-
:userinfo_signed_response_algs,
|
30
|
-
:userinfo_encrypted_response_algs,
|
31
|
-
:id_token_signed_response_algs,
|
32
|
-
:id_token_encrypted_response_algs
|
39
|
+
:redirect_uris
|
33
40
|
]
|
34
41
|
attr_required :endpoint
|
35
42
|
attr_optional *(singular_attributes + plurar_attributes)
|
@@ -48,10 +55,10 @@ module OpenIDConnect
|
|
48
55
|
end
|
49
56
|
|
50
57
|
validates :type, :presence => true
|
51
|
-
validates :client_id, :presence => {:if => lambda { |c| c.type.to_s
|
58
|
+
validates :client_id, :presence => {:if => lambda { |c| ['client_update', 'rotate_secret'].include?(c.type.to_s) }}
|
52
59
|
validates :sector_identifier_url, :presence => {:if => :sector_identifier_required?}
|
53
60
|
|
54
|
-
validates :type, :inclusion => {:in => ['client_associate', 'client_update']}
|
61
|
+
validates :type, :inclusion => {:in => ['client_associate', 'rotate_secret', 'client_update']}
|
55
62
|
validates :application_type, :inclusion => {:in => ['native', 'web']}, :allow_nil => true
|
56
63
|
validates :user_id_type, :inclusion => {:in => ['pairwise', 'public']}, :allow_nil => true
|
57
64
|
validates :token_endpoint_auth_type, :inclusion => {
|
@@ -127,6 +134,11 @@ module OpenIDConnect
|
|
127
134
|
post!
|
128
135
|
end
|
129
136
|
|
137
|
+
def rotate_secret!
|
138
|
+
self.type = 'rotate_secret'
|
139
|
+
post!
|
140
|
+
end
|
141
|
+
|
130
142
|
def update!
|
131
143
|
self.type = 'client_update'
|
132
144
|
post!
|
@@ -6,8 +6,6 @@ module OpenIDConnect
|
|
6
6
|
def self.parse(identifier)
|
7
7
|
raise InvalidIdentifier.new('Identifier Required') if identifier.blank?
|
8
8
|
type = case identifier
|
9
|
-
when /^(=|@|!)/
|
10
|
-
XRI
|
11
9
|
when /@/
|
12
10
|
Email
|
13
11
|
else
|
@@ -31,5 +29,4 @@ module OpenIDConnect
|
|
31
29
|
end
|
32
30
|
|
33
31
|
require 'openid_connect/discovery/principal/email'
|
34
|
-
require 'openid_connect/discovery/principal/uri'
|
35
|
-
require 'openid_connect/discovery/principal/xri'
|
32
|
+
require 'openid_connect/discovery/principal/uri'
|
@@ -6,7 +6,7 @@ module OpenIDConnect
|
|
6
6
|
class InvalidToken < Exception; end
|
7
7
|
|
8
8
|
attr_required :iss, :user_id, :aud, :exp, :iat
|
9
|
-
attr_optional :acr, :auth_time, :nonce
|
9
|
+
attr_optional :acr, :auth_time, :nonce, :at_hash
|
10
10
|
|
11
11
|
def initialize(attributes = {})
|
12
12
|
super
|
@@ -25,16 +25,8 @@ module OpenIDConnect
|
|
25
25
|
|
26
26
|
include JWTnizable
|
27
27
|
class << self
|
28
|
-
def decode(jwt_string,
|
29
|
-
|
30
|
-
when Client
|
31
|
-
OpenIDConnect::AccessToken.new(
|
32
|
-
:client => key_or_client,
|
33
|
-
:access_token => jwt_string
|
34
|
-
).id_token!
|
35
|
-
else
|
36
|
-
new JSON::JWT.decode(jwt_string, key_or_client)
|
37
|
-
end
|
28
|
+
def decode(jwt_string, key)
|
29
|
+
new JSON::JWT.decode(jwt_string, key)
|
38
30
|
end
|
39
31
|
end
|
40
32
|
end
|
@@ -4,7 +4,6 @@
|
|
4
4
|
"authorization_endpoint": "https://connect-op.heroku.com/authorizations/new",
|
5
5
|
"token_endpoint": "https://connect-op.heroku.com/access_tokens",
|
6
6
|
"userinfo_endpoint": "https://connect-op.heroku.com/user_info",
|
7
|
-
"check_id_endpoint": "https://connect-op.heroku.com/id_token",
|
8
7
|
"registration_endpoint": "https://connect-op.heroku.com/connect/client",
|
9
8
|
"scopes_supported": ["openid", "profile", "email", "address"],
|
10
9
|
"response_types_supported": ["code", "token", "id_token", "code token", "code id_token", "id_token token"],
|
@@ -97,18 +97,4 @@ describe OpenIDConnect::AccessToken do
|
|
97
97
|
it_behaves_like :access_token_error_handling
|
98
98
|
end
|
99
99
|
end
|
100
|
-
|
101
|
-
describe '#id_token!' do
|
102
|
-
it 'should return OpenIDConnect::ResponseObject::UserInfo::OpenID' do
|
103
|
-
mock_json :get, client.check_id_uri, 'id_token', :HTTP_AUTHORIZATION => 'Bearer access_token' do
|
104
|
-
access_token.id_token!.should be_a OpenIDConnect::ResponseObject::IdToken
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
describe 'error handling' do
|
109
|
-
let(:endpoint) { client.check_id_uri }
|
110
|
-
let(:request) { access_token.id_token! }
|
111
|
-
it_behaves_like :access_token_error_handling
|
112
|
-
end
|
113
|
-
end
|
114
100
|
end
|
@@ -224,7 +224,7 @@ describe OpenIDConnect::Client::Registrar do
|
|
224
224
|
} do
|
225
225
|
client = instance.associate!
|
226
226
|
client.should be_instance_of OpenIDConnect::Client
|
227
|
-
client.identifier.should == '
|
227
|
+
client.identifier.should == 'client.example.com'
|
228
228
|
client.secret.should == 'client_secret'
|
229
229
|
client.expires_in.should == 3600
|
230
230
|
end
|
@@ -255,13 +255,13 @@ describe OpenIDConnect::Client::Registrar do
|
|
255
255
|
mock_json :post, endpoint, 'client/updated', :params => {
|
256
256
|
:type => 'client_update',
|
257
257
|
:client_id => 'client.example.com',
|
258
|
-
:client_secret => 'client_secret'
|
258
|
+
:client_secret => 'client_secret',
|
259
|
+
:application_name => 'New Name'
|
259
260
|
} do
|
261
|
+
instance.application_name = 'New Name'
|
260
262
|
client = instance.update!
|
261
263
|
client.should be_instance_of OpenIDConnect::Client
|
262
|
-
client.identifier.should == '
|
263
|
-
client.secret.should == 'new_client_secret'
|
264
|
-
client.expires_in.should == 3600
|
264
|
+
client.identifier.should == 'client.example.com'
|
265
265
|
end
|
266
266
|
end
|
267
267
|
|
@@ -280,6 +280,29 @@ describe OpenIDConnect::Client::Registrar do
|
|
280
280
|
end
|
281
281
|
end
|
282
282
|
|
283
|
+
describe '#rotate_secret!' do
|
284
|
+
let(:attributes) do
|
285
|
+
{
|
286
|
+
:client_id => 'client.example.com',
|
287
|
+
:client_secret => 'client_secret'
|
288
|
+
}
|
289
|
+
end
|
290
|
+
|
291
|
+
it 'should return OpenIDConnect::Client' do
|
292
|
+
mock_json :post, endpoint, 'client/rotated', :params => {
|
293
|
+
:type => 'rotate_secret',
|
294
|
+
:client_id => 'client.example.com',
|
295
|
+
:client_secret => 'client_secret'
|
296
|
+
} do
|
297
|
+
client = instance.rotate_secret!
|
298
|
+
client.should be_instance_of OpenIDConnect::Client
|
299
|
+
client.identifier.should == 'client.example.com'
|
300
|
+
client.secret.should == 'new_client_secret'
|
301
|
+
client.expires_in.should == 3600
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
283
306
|
describe '#validate!' do
|
284
307
|
context 'when valid' do
|
285
308
|
it do
|
@@ -19,12 +19,11 @@ describe OpenIDConnect::Client do
|
|
19
19
|
end
|
20
20
|
its(:authorization_uri) { should include 'https://server.example.com/oauth2/authorize' }
|
21
21
|
its(:authorization_uri) { should include 'scope=openid' }
|
22
|
-
its(:check_id_uri) { should == 'https://server.example.com/id_token' }
|
23
22
|
its(:user_info_uri) { should == 'https://server.example.com/user_info' }
|
24
23
|
end
|
25
24
|
|
26
25
|
context 'otherwise' do
|
27
|
-
[:authorization_uri, :
|
26
|
+
[:authorization_uri, :user_info_uri].each do |endpoint|
|
28
27
|
describe endpoint do
|
29
28
|
it do
|
30
29
|
expect { client.send endpoint }.should raise_error 'No Host Info'
|
@@ -5,9 +5,7 @@ describe OpenIDConnect::Discovery::Principal do
|
|
5
5
|
{
|
6
6
|
'server.example.com' => OpenIDConnect::Discovery::Principal::URI,
|
7
7
|
'http://server.example.com' => OpenIDConnect::Discovery::Principal::URI,
|
8
|
-
'nov@server.example.com' => OpenIDConnect::Discovery::Principal::Email
|
9
|
-
'=nov' => OpenIDConnect::Discovery::Principal::XRI,
|
10
|
-
'@nov' => OpenIDConnect::Discovery::Principal::XRI
|
8
|
+
'nov@server.example.com' => OpenIDConnect::Discovery::Principal::Email
|
11
9
|
}.each do |input, klass|
|
12
10
|
describe input do
|
13
11
|
it do
|
@@ -14,7 +14,6 @@ describe OpenIDConnect::Discovery::Provider::Config do
|
|
14
14
|
config.authorization_endpoint.should == 'https://connect-op.heroku.com/authorizations/new'
|
15
15
|
config.token_endpoint.should == 'https://connect-op.heroku.com/access_tokens'
|
16
16
|
config.user_info_endpoint.should == 'https://connect-op.heroku.com/user_info'
|
17
|
-
config.check_id_endpoint.should == 'https://connect-op.heroku.com/id_token'
|
18
17
|
config.refresh_session_endpoint.should be_nil
|
19
18
|
config.end_session_endpoint.should be_nil
|
20
19
|
config.jwk_url.should be_nil
|
@@ -19,7 +19,7 @@ describe OpenIDConnect::ResponseObject::IdToken do
|
|
19
19
|
describe 'attributes' do
|
20
20
|
subject { klass }
|
21
21
|
its(:required_attributes) { should == [:iss, :user_id, :aud, :exp, :iat] }
|
22
|
-
its(:optional_attributes) { should == [:acr, :auth_time, :nonce] }
|
22
|
+
its(:optional_attributes) { should == [:acr, :auth_time, :nonce, :at_hash] }
|
23
23
|
end
|
24
24
|
|
25
25
|
describe '#verify!' do
|
@@ -150,37 +150,12 @@ describe OpenIDConnect::ResponseObject::IdToken do
|
|
150
150
|
end
|
151
151
|
|
152
152
|
describe '.decode' do
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
its(key) { should == attributes[key] }
|
159
|
-
end
|
160
|
-
its(:exp) { should == attributes[:exp].to_i }
|
161
|
-
end
|
162
|
-
|
163
|
-
context 'when client is given' do
|
164
|
-
let :client do
|
165
|
-
OpenIDConnect::Client.new(
|
166
|
-
:identifier => 'client_id',
|
167
|
-
:secret => 'client_secret',
|
168
|
-
:host => 'server.example.com'
|
169
|
-
)
|
170
|
-
end
|
171
|
-
subject do
|
172
|
-
mock_json :get, client.check_id_uri, 'id_token', :HTTP_AUTHORIZATION => 'Bearer access_token' do
|
173
|
-
@subject = klass.decode id_token.to_jwt(private_key), client
|
174
|
-
end
|
175
|
-
@subject
|
176
|
-
end
|
177
|
-
let(:attributes) { required_attributes }
|
178
|
-
let(:ext) { 1303852880 }
|
179
|
-
it { should be_a klass }
|
180
|
-
[:iss, :user_id, :aud].each do |key|
|
181
|
-
its(key) { should == attributes[key] }
|
182
|
-
end
|
183
|
-
its(:exp) { should == attributes[:exp].to_i }
|
153
|
+
subject { klass.decode id_token.to_jwt(private_key), public_key }
|
154
|
+
let(:attributes) { required_attributes }
|
155
|
+
it { should be_a klass }
|
156
|
+
[:iss, :user_id, :aud].each do |key|
|
157
|
+
its(key) { should == attributes[key] }
|
184
158
|
end
|
159
|
+
its(:exp) { should == attributes[:exp].to_i }
|
185
160
|
end
|
186
161
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openid_connect
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -246,7 +246,6 @@ files:
|
|
246
246
|
- lib/openid_connect/discovery/principal.rb
|
247
247
|
- lib/openid_connect/discovery/principal/email.rb
|
248
248
|
- lib/openid_connect/discovery/principal/uri.rb
|
249
|
-
- lib/openid_connect/discovery/principal/xri.rb
|
250
249
|
- lib/openid_connect/discovery/provider.rb
|
251
250
|
- lib/openid_connect/discovery/provider/config.rb
|
252
251
|
- lib/openid_connect/discovery/provider/config/resource.rb
|
@@ -276,6 +275,7 @@ files:
|
|
276
275
|
- spec/mock_response/access_token/invalid_json.json
|
277
276
|
- spec/mock_response/access_token/mac.json
|
278
277
|
- spec/mock_response/client/registered.json
|
278
|
+
- spec/mock_response/client/rotated.json
|
279
279
|
- spec/mock_response/client/updated.json
|
280
280
|
- spec/mock_response/discovery/config.json
|
281
281
|
- spec/mock_response/discovery/swd.json
|
@@ -292,7 +292,6 @@ files:
|
|
292
292
|
- spec/openid_connect/debugger/request_filter_spec.rb
|
293
293
|
- spec/openid_connect/discovery/principal/email_spec.rb
|
294
294
|
- spec/openid_connect/discovery/principal/uri_spec.rb
|
295
|
-
- spec/openid_connect/discovery/principal/xri_spec.rb
|
296
295
|
- spec/openid_connect/discovery/principal_spec.rb
|
297
296
|
- spec/openid_connect/discovery/provider/config/response_spec.rb
|
298
297
|
- spec/openid_connect/discovery/provider/config_spec.rb
|
@@ -342,6 +341,7 @@ test_files:
|
|
342
341
|
- spec/mock_response/access_token/invalid_json.json
|
343
342
|
- spec/mock_response/access_token/mac.json
|
344
343
|
- spec/mock_response/client/registered.json
|
344
|
+
- spec/mock_response/client/rotated.json
|
345
345
|
- spec/mock_response/client/updated.json
|
346
346
|
- spec/mock_response/discovery/config.json
|
347
347
|
- spec/mock_response/discovery/swd.json
|
@@ -358,7 +358,6 @@ test_files:
|
|
358
358
|
- spec/openid_connect/debugger/request_filter_spec.rb
|
359
359
|
- spec/openid_connect/discovery/principal/email_spec.rb
|
360
360
|
- spec/openid_connect/discovery/principal/uri_spec.rb
|
361
|
-
- spec/openid_connect/discovery/principal/xri_spec.rb
|
362
361
|
- spec/openid_connect/discovery/principal_spec.rb
|
363
362
|
- spec/openid_connect/discovery/provider/config/response_spec.rb
|
364
363
|
- spec/openid_connect/discovery/provider/config_spec.rb
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module OpenIDConnect
|
2
|
-
module Discovery
|
3
|
-
class Principal
|
4
|
-
class XRI < Principal
|
5
|
-
def initialize(identifier)
|
6
|
-
@identifier = identifier
|
7
|
-
end
|
8
|
-
|
9
|
-
def discover!(cache_options = {})
|
10
|
-
raise NotImplementedError.new('XRI is not supported yet')
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|