doorkeeper 2.1.4 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of doorkeeper might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -430
- data/Gemfile +1 -8
- data/NEWS.md +449 -0
- data/README.md +46 -3
- data/doorkeeper.gemspec +1 -1
- data/gemfiles/Gemfile.common.rb +0 -7
- data/gemfiles/Gemfile.mongo_mapper.rb +2 -2
- data/gemfiles/Gemfile.mongoid2.rb +1 -1
- data/gemfiles/Gemfile.mongoid4.rb +0 -1
- data/lib/doorkeeper/config.rb +7 -0
- data/lib/doorkeeper/engine.rb +4 -0
- data/lib/doorkeeper/errors.rb +6 -0
- data/lib/doorkeeper/models/access_token_mixin.rb +6 -1
- data/lib/doorkeeper/rails/helpers.rb +1 -1
- data/lib/doorkeeper/version.rb +1 -1
- data/lib/generators/doorkeeper/templates/initializer.rb +4 -0
- data/spec/controllers/applications_controller_spec.rb +0 -1
- data/spec/controllers/token_info_controller_spec.rb +0 -4
- data/spec/controllers/tokens_controller_spec.rb +4 -3
- data/spec/dummy/config/application.rb +2 -0
- data/spec/lib/config_spec.rb +18 -2
- data/spec/lib/oauth/authorization_code_request_spec.rb +1 -1
- data/spec/lib/oauth/client/credentials_spec.rb +2 -2
- data/spec/lib/oauth/password_access_token_request_spec.rb +1 -1
- data/spec/lib/oauth/pre_authorization_spec.rb +9 -10
- data/spec/lib/oauth/refresh_token_request_spec.rb +0 -1
- data/spec/lib/oauth/token_request_spec.rb +3 -3
- data/spec/lib/server_spec.rb +3 -1
- data/spec/models/doorkeeper/access_token_spec.rb +48 -0
- data/spec/requests/applications/applications_request_spec.rb +1 -1
- data/spec/requests/endpoints/authorization_spec.rb +2 -1
- data/spec/requests/endpoints/token_spec.rb +9 -9
- data/spec/requests/flows/authorization_code_errors_spec.rb +4 -4
- data/spec/requests/flows/authorization_code_spec.rb +10 -2
- data/spec/requests/flows/implicit_grant_spec.rb +14 -5
- data/spec/requests/flows/password_spec.rb +14 -20
- data/spec/requests/flows/refresh_token_spec.rb +7 -7
- data/spec/requests/flows/revoke_token_spec.rb +9 -31
- data/spec/requests/protected_resources/metal_spec.rb +3 -3
- data/spec/requests/protected_resources/private_api_spec.rb +11 -0
- data/spec/routing/custom_controller_routes_spec.rb +1 -2
- data/spec/routing/default_routes_spec.rb +1 -2
- data/spec/routing/scoped_routes_spec.rb +0 -1
- data/spec/spec_helper_integration.rb +3 -1
- data/spec/support/helpers/access_token_request_helper.rb +1 -1
- data/spec/support/helpers/authorization_request_helper.rb +1 -1
- data/spec/support/helpers/config_helper.rb +1 -1
- data/spec/support/helpers/model_helper.rb +1 -1
- data/spec/support/helpers/request_spec_helper.rb +1 -1
- data/spec/support/helpers/url_helper.rb +1 -1
- metadata +5 -4
data/doorkeeper.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.add_dependency "railties", ">= 3.2"
|
20
20
|
|
21
21
|
s.add_development_dependency "sqlite3", "~> 1.3.5"
|
22
|
-
s.add_development_dependency "rspec-rails", "~>
|
22
|
+
s.add_development_dependency "rspec-rails", "~> 3.1.0"
|
23
23
|
s.add_development_dependency "capybara", "~> 2.3.0"
|
24
24
|
s.add_development_dependency "generator_spec", "~> 0.9.0"
|
25
25
|
s.add_development_dependency "factory_girl", "~> 4.5.0"
|
data/gemfiles/Gemfile.common.rb
CHANGED
data/lib/doorkeeper/config.rb
CHANGED
@@ -108,6 +108,12 @@ and that your `initialize_models!` method doesn't raise any errors.\n
|
|
108
108
|
def force_ssl_in_redirect_uri(boolean)
|
109
109
|
@config.instance_variable_set("@force_ssl_in_redirect_uri", boolean)
|
110
110
|
end
|
111
|
+
|
112
|
+
def access_token_generator(access_token_generator)
|
113
|
+
@config.instance_variable_set(
|
114
|
+
'@access_token_generator', access_token_generator
|
115
|
+
)
|
116
|
+
end
|
111
117
|
end
|
112
118
|
|
113
119
|
module Option
|
@@ -198,6 +204,7 @@ and that your `initialize_models!` method doesn't raise any errors.\n
|
|
198
204
|
option :realm, default: 'Doorkeeper'
|
199
205
|
option :force_ssl_in_redirect_uri, default: !Rails.env.development?
|
200
206
|
option :grant_flows, default: %w(authorization_code client_credentials)
|
207
|
+
option :access_token_generator, default: "Doorkeeper::OAuth::Helpers::UniqueToken"
|
201
208
|
|
202
209
|
attr_reader :reuse_access_token
|
203
210
|
|
data/lib/doorkeeper/engine.rb
CHANGED
data/lib/doorkeeper/errors.rb
CHANGED
@@ -128,7 +128,12 @@ module Doorkeeper
|
|
128
128
|
end
|
129
129
|
|
130
130
|
def generate_token
|
131
|
-
|
131
|
+
generator = Doorkeeper.configuration.access_token_generator.constantize
|
132
|
+
self.token = generator.generate(resource_owner_id: resource_owner_id)
|
133
|
+
rescue NoMethodError
|
134
|
+
raise Errors::UnableToGenerateToken, "#{generator} does not respond to `.generate`."
|
135
|
+
rescue NameError
|
136
|
+
raise Errors::TokenGeneratorNotFound, "#{generator} not found"
|
132
137
|
end
|
133
138
|
end
|
134
139
|
end
|
@@ -4,7 +4,7 @@ module Doorkeeper
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
def doorkeeper_authorize!(*scopes)
|
7
|
-
@_doorkeeper_scopes = scopes || Doorkeeper.configuration.default_scopes
|
7
|
+
@_doorkeeper_scopes = scopes.presence || Doorkeeper.configuration.default_scopes
|
8
8
|
|
9
9
|
if !valid_doorkeeper_token?
|
10
10
|
doorkeeper_render_error
|
data/lib/doorkeeper/version.rb
CHANGED
@@ -31,6 +31,10 @@ Doorkeeper.configure do
|
|
31
31
|
# oauth_client.application.additional_settings.implicit_oauth_expiration
|
32
32
|
# end
|
33
33
|
|
34
|
+
# Use a custom class for generating the access token.
|
35
|
+
# https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
|
36
|
+
# access_token_generator "::Doorkeeper::JWT"
|
37
|
+
|
34
38
|
# Reuse access token for the same resource owner within an application (disabled by default)
|
35
39
|
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
|
36
40
|
# reuse_access_token
|
@@ -1,9 +1,7 @@
|
|
1
1
|
require 'spec_helper_integration'
|
2
2
|
|
3
3
|
describe Doorkeeper::TokenInfoController do
|
4
|
-
|
5
4
|
describe 'when requesting tokeninfo with valid token' do
|
6
|
-
|
7
5
|
let(:doorkeeper_token) { FactoryGirl.create(:access_token) }
|
8
6
|
|
9
7
|
before(:each) do
|
@@ -50,7 +48,5 @@ describe Doorkeeper::TokenInfoController do
|
|
50
48
|
expect(response.body).to eq(Doorkeeper::OAuth::ErrorResponse.new(name: :invalid_request, status: :unauthorized).body.to_json)
|
51
49
|
end
|
52
50
|
end
|
53
|
-
|
54
51
|
end
|
55
|
-
|
56
52
|
end
|
@@ -12,7 +12,9 @@ describe Doorkeeper::TokensController do
|
|
12
12
|
|
13
13
|
it 'returns the authorization' do
|
14
14
|
skip 'verify need of these specs'
|
15
|
+
|
15
16
|
expect(token).to receive(:authorization)
|
17
|
+
|
16
18
|
post :create
|
17
19
|
end
|
18
20
|
end
|
@@ -46,11 +48,10 @@ describe Doorkeeper::TokensController do
|
|
46
48
|
strategy = double(:strategy, authorize: true)
|
47
49
|
expect(strategy).to receive(:authorize).once
|
48
50
|
allow(controller).to receive(:strategy) { strategy }
|
49
|
-
|
50
|
-
controller.stub(:create) do
|
51
|
-
controller.send :authorize_response
|
51
|
+
allow(controller).to receive(:create) do
|
52
52
|
controller.send :authorize_response
|
53
53
|
end
|
54
|
+
|
54
55
|
post :create
|
55
56
|
end
|
56
57
|
end
|
data/spec/lib/config_spec.rb
CHANGED
@@ -22,7 +22,7 @@ describe Doorkeeper, 'configuration' do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'does not change other exceptions' do
|
25
|
-
String.
|
25
|
+
allow_any_instance_of(String).to receive(:classify) { raise NoMethodError }
|
26
26
|
|
27
27
|
expect do
|
28
28
|
Doorkeeper.configure { orm 'hibernate' }
|
@@ -35,7 +35,7 @@ describe Doorkeeper, 'configuration' do
|
|
35
35
|
block = proc {}
|
36
36
|
Doorkeeper.configure do
|
37
37
|
orm DOORKEEPER_ORM
|
38
|
-
admin_authenticator
|
38
|
+
admin_authenticator(&block)
|
39
39
|
end
|
40
40
|
expect(subject.authenticate_admin).to eq(block)
|
41
41
|
end
|
@@ -298,4 +298,20 @@ describe Doorkeeper, 'configuration' do
|
|
298
298
|
@config = old_config
|
299
299
|
end
|
300
300
|
end
|
301
|
+
|
302
|
+
describe 'access_token_generator' do
|
303
|
+
it 'is \'Doorkeeper::OAuth::Helpers::UniqueToken\' by default' do
|
304
|
+
expect(Doorkeeper.configuration.access_token_generator).to(
|
305
|
+
eq('Doorkeeper::OAuth::Helpers::UniqueToken')
|
306
|
+
)
|
307
|
+
end
|
308
|
+
|
309
|
+
it 'can change the value' do
|
310
|
+
Doorkeeper.configure do
|
311
|
+
orm DOORKEEPER_ORM
|
312
|
+
access_token_generator 'Example'
|
313
|
+
end
|
314
|
+
expect(subject.access_token_generator).to eq('Example')
|
315
|
+
end
|
316
|
+
end
|
301
317
|
end
|
@@ -69,7 +69,7 @@ module Doorkeeper::OAuth
|
|
69
69
|
end
|
70
70
|
|
71
71
|
it 'skips token creation if there is a matching one' do
|
72
|
-
Doorkeeper.configuration.
|
72
|
+
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
73
73
|
FactoryGirl.create(:access_token, application_id: client.id,
|
74
74
|
resource_owner_id: grant.resource_owner_id, scopes: grant.scopes.to_s)
|
75
75
|
expect do
|
@@ -13,7 +13,7 @@ class Doorkeeper::OAuth::Client
|
|
13
13
|
let(:request) { double.as_null_object }
|
14
14
|
|
15
15
|
let(:method) do
|
16
|
-
->(
|
16
|
+
->(_request) { return 'uid', 'secret' }
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'accepts anything that responds to #call' do
|
@@ -29,7 +29,7 @@ class Doorkeeper::OAuth::Client
|
|
29
29
|
it 'stops at the first credentials found' do
|
30
30
|
not_called_method = double
|
31
31
|
expect(not_called_method).not_to receive(:call)
|
32
|
-
|
32
|
+
Credentials.from_request request, ->(_) {}, method, not_called_method
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'returns new Credentials' do
|
@@ -60,7 +60,7 @@ module Doorkeeper::OAuth
|
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'skips token creation if there is already one' do
|
63
|
-
Doorkeeper.configuration.
|
63
|
+
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
64
64
|
FactoryGirl.create(:access_token, application_id: client.id, resource_owner_id: owner.id)
|
65
65
|
expect do
|
66
66
|
subject.authorize
|
@@ -4,14 +4,14 @@ module Doorkeeper::OAuth
|
|
4
4
|
describe PreAuthorization do
|
5
5
|
let(:server) {
|
6
6
|
server = Doorkeeper.configuration
|
7
|
-
server.
|
8
|
-
server.
|
7
|
+
allow(server).to receive(:default_scopes).and_return(Scopes.new)
|
8
|
+
allow(server).to receive(:scopes).and_return(Scopes.from_string('public profile'))
|
9
9
|
server
|
10
10
|
}
|
11
11
|
|
12
12
|
let(:application) do
|
13
13
|
application = double :application
|
14
|
-
application.
|
14
|
+
allow(application).to receive(:scopes).and_return(Scopes.from_string(''))
|
15
15
|
application
|
16
16
|
end
|
17
17
|
|
@@ -41,7 +41,7 @@ module Doorkeeper::OAuth
|
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'accepts token as response type' do
|
44
|
-
server.
|
44
|
+
allow(server).to receive(:grant_flows).and_return(['implicit'])
|
45
45
|
subject.response_type = 'token'
|
46
46
|
expect(subject).to be_authorizable
|
47
47
|
end
|
@@ -53,7 +53,7 @@ module Doorkeeper::OAuth
|
|
53
53
|
end
|
54
54
|
|
55
55
|
it 'accepts "token" as response type' do
|
56
|
-
server.
|
56
|
+
allow(server).to receive(:grant_flows).and_return(['implicit'])
|
57
57
|
subject.response_type = 'token'
|
58
58
|
expect(subject).to be_authorizable
|
59
59
|
end
|
@@ -61,7 +61,7 @@ module Doorkeeper::OAuth
|
|
61
61
|
|
62
62
|
context 'when authorization code grant flow is disabled' do
|
63
63
|
before do
|
64
|
-
server.
|
64
|
+
allow(server).to receive(:grant_flows).and_return(['implicit'])
|
65
65
|
end
|
66
66
|
|
67
67
|
it 'does not accept "code" as response type' do
|
@@ -72,7 +72,7 @@ module Doorkeeper::OAuth
|
|
72
72
|
|
73
73
|
context 'when implicit grant flow is disabled' do
|
74
74
|
before do
|
75
|
-
server.
|
75
|
+
allow(server).to receive(:grant_flows).and_return(['authorization_code'])
|
76
76
|
end
|
77
77
|
|
78
78
|
it 'does not accept "token" as response type' do
|
@@ -96,7 +96,7 @@ module Doorkeeper::OAuth
|
|
96
96
|
context 'client application restricts valid scopes' do
|
97
97
|
let(:application) do
|
98
98
|
application = double :application
|
99
|
-
application.
|
99
|
+
allow(application).to receive(:scopes).and_return(Scopes.from_string('public nonsense'))
|
100
100
|
application
|
101
101
|
end
|
102
102
|
|
@@ -119,7 +119,7 @@ module Doorkeeper::OAuth
|
|
119
119
|
it 'uses default scopes when none is required' do
|
120
120
|
allow(server).to receive(:default_scopes).and_return(Scopes.from_string('default'))
|
121
121
|
subject.scope = nil
|
122
|
-
expect(subject.scope).to
|
122
|
+
expect(subject.scope).to eq('default')
|
123
123
|
expect(subject.scopes).to eq(Scopes.from_string('default'))
|
124
124
|
end
|
125
125
|
|
@@ -151,6 +151,5 @@ module Doorkeeper::OAuth
|
|
151
151
|
subject.redirect_uri = nil
|
152
152
|
expect(subject).not_to be_authorizable
|
153
153
|
end
|
154
|
-
|
155
154
|
end
|
156
155
|
end
|
@@ -67,14 +67,14 @@ module Doorkeeper::OAuth
|
|
67
67
|
|
68
68
|
context 'token reuse' do
|
69
69
|
it 'creates a new token if there are no matching tokens' do
|
70
|
-
Doorkeeper.configuration.
|
70
|
+
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
71
71
|
expect do
|
72
72
|
subject.authorize
|
73
73
|
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
74
74
|
end
|
75
75
|
|
76
76
|
it 'creates a new token if scopes do not match' do
|
77
|
-
Doorkeeper.configuration.
|
77
|
+
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
78
78
|
FactoryGirl.create(:access_token, application_id: pre_auth.client.id,
|
79
79
|
resource_owner_id: owner.id, scopes: '')
|
80
80
|
expect do
|
@@ -83,7 +83,7 @@ module Doorkeeper::OAuth
|
|
83
83
|
end
|
84
84
|
|
85
85
|
it 'skips token creation if there is a matching one' do
|
86
|
-
Doorkeeper.configuration.
|
86
|
+
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
87
87
|
FactoryGirl.create(:access_token, application_id: pre_auth.client.id,
|
88
88
|
resource_owner_id: owner.id, scopes: 'public')
|
89
89
|
expect do
|
data/spec/lib/server_spec.rb
CHANGED
@@ -25,7 +25,9 @@ describe Doorkeeper::Server do
|
|
25
25
|
|
26
26
|
context 'when only Authorization Code strategy is enabled' do
|
27
27
|
before do
|
28
|
-
Doorkeeper.configuration.
|
28
|
+
allow(Doorkeeper.configuration).
|
29
|
+
to receive(:grant_flows).
|
30
|
+
and_return(['authorization_code'])
|
29
31
|
end
|
30
32
|
|
31
33
|
it 'raises error when using the disabled Implicit strategy' do
|
@@ -12,6 +12,54 @@ module Doorkeeper
|
|
12
12
|
let(:factory_name) { :access_token }
|
13
13
|
end
|
14
14
|
|
15
|
+
describe :generate_token do
|
16
|
+
it 'generates a token using the default method' do
|
17
|
+
FactoryGirl.create :access_token
|
18
|
+
|
19
|
+
token = FactoryGirl.create :access_token
|
20
|
+
expect(token.token).to be_a(String)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'generates a token using a custom object' do
|
24
|
+
module CustomGeneratorArgs
|
25
|
+
def self.generate(opts = {})
|
26
|
+
"custom_generator_token_#{opts[:resource_owner_id]}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Doorkeeper.configure do
|
31
|
+
orm DOORKEEPER_ORM
|
32
|
+
access_token_generator "Doorkeeper::CustomGeneratorArgs"
|
33
|
+
end
|
34
|
+
|
35
|
+
token = FactoryGirl.create :access_token
|
36
|
+
expect(token.token).to match(%r{custom_generator_token_\d})
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'raises an error if the custom object does not support generate' do
|
40
|
+
module NoGenerate
|
41
|
+
end
|
42
|
+
|
43
|
+
Doorkeeper.configure do
|
44
|
+
orm DOORKEEPER_ORM
|
45
|
+
access_token_generator "Doorkeeper::NoGenerate"
|
46
|
+
end
|
47
|
+
|
48
|
+
expect { FactoryGirl.create :access_token }.to(
|
49
|
+
raise_error(Doorkeeper::Errors::UnableToGenerateToken))
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'raises an error if the custom object does not exist' do
|
53
|
+
Doorkeeper.configure do
|
54
|
+
orm DOORKEEPER_ORM
|
55
|
+
access_token_generator "Doorkeeper::NotReal"
|
56
|
+
end
|
57
|
+
|
58
|
+
expect { FactoryGirl.create :access_token }.to(
|
59
|
+
raise_error(Doorkeeper::Errors::TokenGeneratorNotFound))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
15
63
|
describe :refresh_token do
|
16
64
|
it 'has empty refresh token if it was not required' do
|
17
65
|
token = FactoryGirl.create :access_token
|