doorkeeper 4.4.3 → 5.0.3
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 +5 -5
- data/.gitignore +1 -0
- data/.gitlab-ci.yml +16 -0
- data/.travis.yml +7 -0
- data/Appraisals +2 -2
- data/Dangerfile +64 -0
- data/Gemfile +1 -1
- data/NEWS.md +98 -8
- data/README.md +110 -12
- data/Rakefile +6 -0
- data/UPGRADE.md +2 -0
- data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +6 -3
- data/app/controllers/doorkeeper/application_metal_controller.rb +6 -0
- data/app/controllers/doorkeeper/applications_controller.rb +46 -24
- data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +21 -2
- data/app/controllers/doorkeeper/token_info_controller.rb +2 -0
- data/app/controllers/doorkeeper/tokens_controller.rb +4 -6
- data/app/helpers/doorkeeper/dashboard_helper.rb +9 -7
- data/app/validators/redirect_uri_validator.rb +5 -2
- data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
- data/app/views/doorkeeper/applications/_form.html.erb +25 -24
- data/app/views/doorkeeper/applications/edit.html.erb +1 -1
- data/app/views/doorkeeper/applications/index.html.erb +17 -7
- data/app/views/doorkeeper/applications/new.html.erb +1 -1
- data/app/views/doorkeeper/applications/show.html.erb +6 -6
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
- data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
- data/config/locales/en.yml +10 -1
- data/doorkeeper.gemspec +25 -26
- data/gemfiles/rails_5_2.gemfile +1 -1
- data/gemfiles/rails_master.gemfile +4 -1
- data/lib/doorkeeper/config.rb +81 -40
- data/lib/doorkeeper/engine.rb +6 -0
- data/lib/doorkeeper/errors.rb +17 -3
- data/lib/doorkeeper/grape/authorization_decorator.rb +2 -0
- data/lib/doorkeeper/grape/helpers.rb +3 -1
- data/lib/doorkeeper/helpers/controller.rb +9 -2
- data/lib/doorkeeper/models/access_grant_mixin.rb +73 -0
- data/lib/doorkeeper/models/access_token_mixin.rb +44 -25
- data/lib/doorkeeper/models/application_mixin.rb +2 -0
- data/lib/doorkeeper/models/concerns/accessible.rb +2 -0
- data/lib/doorkeeper/models/concerns/expirable.rb +2 -0
- data/lib/doorkeeper/models/concerns/orderable.rb +2 -0
- data/lib/doorkeeper/models/concerns/ownership.rb +2 -0
- data/lib/doorkeeper/models/concerns/revocable.rb +2 -0
- data/lib/doorkeeper/models/concerns/scopes.rb +3 -1
- data/lib/doorkeeper/oauth/authorization/code.rb +33 -8
- data/lib/doorkeeper/oauth/authorization/context.rb +17 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +38 -14
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +2 -0
- data/lib/doorkeeper/oauth/authorization_code_request.rb +29 -2
- data/lib/doorkeeper/oauth/base_request.rb +22 -9
- data/lib/doorkeeper/oauth/base_response.rb +2 -0
- data/lib/doorkeeper/oauth/client/credentials.rb +3 -1
- data/lib/doorkeeper/oauth/client.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +4 -1
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +7 -2
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +5 -5
- data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -3
- data/lib/doorkeeper/oauth/code_request.rb +2 -0
- data/lib/doorkeeper/oauth/code_response.rb +2 -0
- data/lib/doorkeeper/oauth/error.rb +2 -0
- data/lib/doorkeeper/oauth/error_response.rb +21 -3
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +9 -2
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -8
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +2 -0
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +5 -2
- data/lib/doorkeeper/oauth/invalid_token_response.rb +18 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +9 -4
- data/lib/doorkeeper/oauth/pre_authorization.rb +43 -11
- data/lib/doorkeeper/oauth/refresh_token_request.rb +16 -3
- data/lib/doorkeeper/oauth/scopes.rb +3 -1
- data/lib/doorkeeper/oauth/token.rb +7 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +4 -2
- data/lib/doorkeeper/oauth/token_request.rb +2 -0
- data/lib/doorkeeper/oauth/token_response.rb +6 -2
- data/lib/doorkeeper/oauth.rb +13 -0
- data/lib/doorkeeper/orm/active_record/application.rb +75 -12
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
- data/lib/doorkeeper/orm/active_record.rb +4 -0
- data/lib/doorkeeper/rails/helpers.rb +6 -4
- data/lib/doorkeeper/rails/routes/mapper.rb +2 -0
- data/lib/doorkeeper/rails/routes/mapping.rb +2 -0
- data/lib/doorkeeper/rails/routes.rb +23 -8
- data/lib/doorkeeper/rake/db.rake +40 -0
- data/lib/doorkeeper/rake/setup.rake +6 -0
- data/lib/doorkeeper/rake.rb +14 -0
- data/lib/doorkeeper/request/authorization_code.rb +1 -1
- data/lib/doorkeeper/request/client_credentials.rb +1 -1
- data/lib/doorkeeper/request/code.rb +1 -1
- data/lib/doorkeeper/request/password.rb +1 -1
- data/lib/doorkeeper/request/refresh_token.rb +1 -1
- data/lib/doorkeeper/request/strategy.rb +2 -0
- data/lib/doorkeeper/request/token.rb +1 -1
- data/lib/doorkeeper/request.rb +29 -34
- data/lib/doorkeeper/server.rb +2 -0
- data/lib/doorkeeper/stale_records_cleaner.rb +20 -0
- data/lib/doorkeeper/validations.rb +2 -0
- data/lib/doorkeeper/version.rb +6 -24
- data/lib/doorkeeper.rb +20 -17
- data/lib/generators/doorkeeper/application_owner_generator.rb +23 -18
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
- data/lib/generators/doorkeeper/install_generator.rb +17 -9
- data/lib/generators/doorkeeper/migration_generator.rb +23 -18
- data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +29 -24
- data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +96 -13
- data/lib/generators/doorkeeper/templates/migration.rb.erb +2 -3
- data/lib/generators/doorkeeper/views_generator.rb +3 -1
- data/spec/controllers/application_metal_controller_spec.rb +50 -0
- data/spec/controllers/applications_controller_spec.rb +123 -14
- data/spec/controllers/authorizations_controller_spec.rb +334 -51
- data/spec/controllers/protected_resources_controller_spec.rb +60 -18
- data/spec/controllers/token_info_controller_spec.rb +4 -12
- data/spec/controllers/tokens_controller_spec.rb +17 -20
- data/spec/dummy/Rakefile +1 -1
- data/spec/dummy/app/assets/config/manifest.js +2 -0
- data/spec/dummy/app/controllers/custom_authorizations_controller.rb +1 -1
- data/spec/dummy/app/controllers/home_controller.rb +1 -2
- data/spec/dummy/config/application.rb +1 -1
- data/spec/dummy/config/boot.rb +2 -4
- data/spec/dummy/config/environment.rb +1 -1
- data/spec/dummy/config/environments/test.rb +5 -6
- data/spec/dummy/config/initializers/doorkeeper.rb +12 -6
- data/spec/dummy/config/initializers/new_framework_defaults.rb +2 -0
- data/spec/dummy/config/initializers/secret_token.rb +1 -1
- data/spec/dummy/config/routes.rb +3 -42
- data/spec/dummy/config.ru +1 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +4 -4
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +1 -1
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
- data/spec/dummy/db/migrate/{20180210183654_add_confidential_to_application.rb → 20180210183654_add_confidential_to_applications.rb} +1 -1
- data/spec/dummy/db/schema.rb +36 -36
- data/spec/dummy/script/rails +4 -3
- data/spec/factories.rb +6 -6
- data/spec/generators/application_owner_generator_spec.rb +1 -1
- data/spec/generators/confidential_applications_generator_spec.rb +45 -0
- data/spec/generators/install_generator_spec.rb +5 -2
- data/spec/generators/migration_generator_spec.rb +1 -1
- data/spec/generators/pkce_generator_spec.rb +43 -0
- data/spec/generators/previous_refresh_token_generator_spec.rb +1 -1
- data/spec/generators/templates/routes.rb +0 -1
- data/spec/generators/views_generator_spec.rb +2 -2
- data/spec/grape/grape_integration_spec.rb +2 -2
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +105 -39
- data/spec/lib/doorkeeper_spec.rb +6 -131
- data/spec/lib/models/expirable_spec.rb +0 -3
- data/spec/lib/models/revocable_spec.rb +0 -2
- data/spec/lib/models/scopes_spec.rb +0 -4
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
- data/spec/lib/oauth/authorization_code_request_spec.rb +17 -7
- data/spec/lib/oauth/base_request_spec.rb +49 -11
- data/spec/lib/oauth/base_response_spec.rb +1 -1
- data/spec/lib/oauth/client/credentials_spec.rb +2 -4
- data/spec/lib/oauth/client_credentials/creator_spec.rb +5 -1
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +24 -7
- data/spec/lib/oauth/client_credentials/validation_spec.rb +4 -4
- data/spec/lib/oauth/client_credentials_integration_spec.rb +2 -2
- data/spec/lib/oauth/client_credentials_request_spec.rb +3 -5
- data/spec/lib/oauth/client_spec.rb +0 -3
- data/spec/lib/oauth/code_request_spec.rb +5 -3
- data/spec/lib/oauth/code_response_spec.rb +1 -1
- data/spec/lib/oauth/error_response_spec.rb +0 -3
- data/spec/lib/oauth/error_spec.rb +0 -2
- data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +8 -11
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +22 -13
- data/spec/lib/oauth/invalid_token_response_spec.rb +1 -4
- data/spec/lib/oauth/password_access_token_request_spec.rb +53 -6
- data/spec/lib/oauth/pre_authorization_spec.rb +33 -4
- data/spec/lib/oauth/refresh_token_request_spec.rb +22 -14
- data/spec/lib/oauth/scopes_spec.rb +0 -3
- data/spec/lib/oauth/token_request_spec.rb +8 -9
- data/spec/lib/oauth/token_response_spec.rb +0 -1
- data/spec/lib/oauth/token_spec.rb +40 -14
- data/spec/lib/request/strategy_spec.rb +0 -1
- data/spec/lib/server_spec.rb +7 -7
- data/spec/lib/stale_records_cleaner_spec.rb +89 -0
- data/spec/models/doorkeeper/access_grant_spec.rb +44 -1
- data/spec/models/doorkeeper/access_token_spec.rb +80 -32
- data/spec/models/doorkeeper/application_spec.rb +293 -221
- data/spec/requests/applications/applications_request_spec.rb +134 -1
- data/spec/requests/applications/authorized_applications_spec.rb +1 -1
- data/spec/requests/endpoints/authorization_spec.rb +3 -3
- data/spec/requests/endpoints/token_spec.rb +7 -5
- data/spec/requests/flows/authorization_code_errors_spec.rb +2 -2
- data/spec/requests/flows/authorization_code_spec.rb +258 -2
- data/spec/requests/flows/client_credentials_spec.rb +46 -6
- data/spec/requests/flows/implicit_grant_errors_spec.rb +3 -3
- data/spec/requests/flows/implicit_grant_spec.rb +38 -11
- data/spec/requests/flows/password_spec.rb +61 -3
- data/spec/requests/flows/refresh_token_spec.rb +59 -2
- data/spec/requests/flows/revoke_token_spec.rb +20 -20
- data/spec/requests/flows/skip_authorization_spec.rb +16 -11
- data/spec/requests/protected_resources/metal_spec.rb +1 -1
- data/spec/requests/protected_resources/private_api_spec.rb +3 -3
- data/spec/routing/custom_controller_routes_spec.rb +59 -7
- data/spec/routing/default_routes_spec.rb +2 -2
- data/spec/routing/scoped_routes_spec.rb +16 -2
- data/spec/spec_helper.rb +54 -3
- data/spec/spec_helper_integration.rb +2 -74
- data/spec/support/dependencies/{factory_girl.rb → factory_bot.rb} +0 -0
- data/spec/support/doorkeeper_rspec.rb +20 -0
- data/spec/support/helpers/authorization_request_helper.rb +4 -4
- data/spec/support/helpers/model_helper.rb +8 -4
- data/spec/support/helpers/request_spec_helper.rb +10 -2
- data/spec/support/helpers/url_helper.rb +18 -14
- data/spec/support/http_method_shim.rb +12 -16
- data/spec/support/shared/controllers_shared_context.rb +56 -0
- data/spec/validators/redirect_uri_validator_spec.rb +9 -3
- data/spec/version/version_spec.rb +3 -3
- data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
- metadata +54 -35
- data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +0 -31
- data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +0 -11
- data/spec/controllers/application_metal_controller.rb +0 -10
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
module Doorkeeper::OAuth
|
4
4
|
describe RefreshTokenRequest do
|
@@ -9,7 +9,7 @@ module Doorkeeper::OAuth
|
|
9
9
|
let(:server) do
|
10
10
|
double :server,
|
11
11
|
access_token_expires_in: 2.minutes,
|
12
|
-
custom_access_token_expires_in: ->
|
12
|
+
custom_access_token_expires_in: ->(_context) { nil }
|
13
13
|
end
|
14
14
|
|
15
15
|
let(:refresh_token) do
|
@@ -24,20 +24,22 @@ module Doorkeeper::OAuth
|
|
24
24
|
it 'issues a new token for the client' do
|
25
25
|
expect { subject.authorize }.to change { client.reload.access_tokens.count }.by(1)
|
26
26
|
# #sort_by used for MongoDB ORM extensions for valid ordering
|
27
|
-
expect(client.reload.access_tokens.
|
27
|
+
expect(client.reload.access_tokens.max_by(&:created_at).expires_in).to eq(120)
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'issues a new token for the client with custom expires_in' do
|
31
31
|
server = double :server,
|
32
32
|
access_token_expires_in: 2.minutes,
|
33
|
-
custom_access_token_expires_in:
|
33
|
+
custom_access_token_expires_in: lambda { |context|
|
34
|
+
context.grant_type == Doorkeeper::OAuth::REFRESH_TOKEN ? 1234 : nil
|
35
|
+
}
|
34
36
|
|
35
37
|
allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
|
36
38
|
|
37
39
|
RefreshTokenRequest.new(server, refresh_token, credentials).authorize
|
38
40
|
|
39
41
|
# #sort_by used for MongoDB ORM extensions for valid ordering
|
40
|
-
expect(client.reload.access_tokens.
|
42
|
+
expect(client.reload.access_tokens.max_by(&:created_at).expires_in).to eq(1234)
|
41
43
|
end
|
42
44
|
|
43
45
|
it 'revokes the previous token' do
|
@@ -45,8 +47,12 @@ module Doorkeeper::OAuth
|
|
45
47
|
end
|
46
48
|
|
47
49
|
it "calls configured request callback methods" do
|
48
|
-
expect(Doorkeeper.configuration.before_successful_strategy_response)
|
49
|
-
|
50
|
+
expect(Doorkeeper.configuration.before_successful_strategy_response)
|
51
|
+
.to receive(:call).with(subject).once
|
52
|
+
|
53
|
+
expect(Doorkeeper.configuration.after_successful_strategy_response)
|
54
|
+
.to receive(:call).with(subject, instance_of(Doorkeeper::OAuth::TokenResponse)).once
|
55
|
+
|
50
56
|
subject.authorize
|
51
57
|
end
|
52
58
|
|
@@ -85,7 +91,9 @@ module Doorkeeper::OAuth
|
|
85
91
|
let(:server) do
|
86
92
|
double :server,
|
87
93
|
access_token_expires_in: 2.minutes,
|
88
|
-
custom_access_token_expires_in:
|
94
|
+
custom_access_token_expires_in: lambda { |context|
|
95
|
+
context.grant_type == Doorkeeper::OAuth::REFRESH_TOKEN ? 1234 : nil
|
96
|
+
}
|
89
97
|
end
|
90
98
|
|
91
99
|
before do
|
@@ -105,7 +113,7 @@ module Doorkeeper::OAuth
|
|
105
113
|
subject.authorize
|
106
114
|
expect(
|
107
115
|
# #sort_by used for MongoDB ORM extensions for valid ordering
|
108
|
-
client.access_tokens.
|
116
|
+
client.access_tokens.max_by(&:created_at).previous_refresh_token
|
109
117
|
).to eq(refresh_token.refresh_token)
|
110
118
|
end
|
111
119
|
end
|
@@ -123,21 +131,21 @@ module Doorkeeper::OAuth
|
|
123
131
|
context 'with scopes' do
|
124
132
|
let(:refresh_token) do
|
125
133
|
FactoryBot.create :access_token,
|
126
|
-
|
127
|
-
|
134
|
+
use_refresh_token: true,
|
135
|
+
scopes: 'public write'
|
128
136
|
end
|
129
137
|
let(:parameters) { {} }
|
130
138
|
subject { RefreshTokenRequest.new server, refresh_token, credentials, parameters }
|
131
139
|
|
132
140
|
it 'transfers scopes from the old token to the new token' do
|
133
141
|
subject.authorize
|
134
|
-
expect(Doorkeeper::AccessToken.last.scopes).to eq([
|
142
|
+
expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public write])
|
135
143
|
end
|
136
144
|
|
137
145
|
it 'reduces scopes to the provided scopes' do
|
138
146
|
parameters[:scopes] = 'public'
|
139
147
|
subject.authorize
|
140
|
-
expect(Doorkeeper::AccessToken.last.scopes).to eq([
|
148
|
+
expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public])
|
141
149
|
end
|
142
150
|
|
143
151
|
it 'validates that scopes are included in the original access token' do
|
@@ -151,7 +159,7 @@ module Doorkeeper::OAuth
|
|
151
159
|
parameters[:scopes] = 'public update'
|
152
160
|
parameters[:scope] = 'public'
|
153
161
|
subject.authorize
|
154
|
-
expect(Doorkeeper::AccessToken.last.scopes).to eq([
|
162
|
+
expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public])
|
155
163
|
end
|
156
164
|
|
157
165
|
it 'uses params[:scope] in favor of scopes if present (invalid)' do
|
@@ -1,10 +1,9 @@
|
|
1
|
-
require '
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
module Doorkeeper::OAuth
|
4
4
|
describe TokenRequest do
|
5
5
|
let :application do
|
6
|
-
|
7
|
-
double(:application, id: 9990, scopes: scopes)
|
6
|
+
FactoryBot.create(:application, scopes: 'public')
|
8
7
|
end
|
9
8
|
|
10
9
|
let :pre_auth do
|
@@ -39,7 +38,7 @@ module Doorkeeper::OAuth
|
|
39
38
|
|
40
39
|
it 'does not create token when not authorizable' do
|
41
40
|
allow(pre_auth).to receive(:authorizable?).and_return(false)
|
42
|
-
expect { subject.authorize }.not_to
|
41
|
+
expect { subject.authorize }.not_to(change { Doorkeeper::AccessToken.count })
|
43
42
|
end
|
44
43
|
|
45
44
|
it 'returns a error response' do
|
@@ -51,8 +50,8 @@ module Doorkeeper::OAuth
|
|
51
50
|
before do
|
52
51
|
Doorkeeper.configure do
|
53
52
|
orm DOORKEEPER_ORM
|
54
|
-
custom_access_token_expires_in do |
|
55
|
-
1234
|
53
|
+
custom_access_token_expires_in do |context|
|
54
|
+
context.grant_type == Doorkeeper::OAuth::IMPLICIT ? 1234 : nil
|
56
55
|
end
|
57
56
|
end
|
58
57
|
end
|
@@ -75,7 +74,7 @@ module Doorkeeper::OAuth
|
|
75
74
|
it 'creates a new token if scopes do not match' do
|
76
75
|
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
77
76
|
FactoryBot.create(:access_token, application_id: pre_auth.client.id,
|
78
|
-
|
77
|
+
resource_owner_id: owner.id, scopes: '')
|
79
78
|
expect do
|
80
79
|
subject.authorize
|
81
80
|
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
@@ -87,9 +86,9 @@ module Doorkeeper::OAuth
|
|
87
86
|
allow(application.scopes).to receive(:all?).and_return(true)
|
88
87
|
|
89
88
|
FactoryBot.create(:access_token, application_id: pre_auth.client.id,
|
90
|
-
|
89
|
+
resource_owner_id: owner.id, scopes: 'public')
|
91
90
|
|
92
|
-
expect { subject.authorize }.not_to
|
91
|
+
expect { subject.authorize }.not_to(change { Doorkeeper::AccessToken.count })
|
93
92
|
end
|
94
93
|
end
|
95
94
|
end
|
@@ -1,6 +1,4 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'active_support/core_ext/string'
|
3
|
-
require 'doorkeeper/oauth/token'
|
4
2
|
|
5
3
|
module Doorkeeper
|
6
4
|
unless defined?(AccessToken)
|
@@ -14,7 +12,7 @@ module Doorkeeper
|
|
14
12
|
let(:request) { double.as_null_object }
|
15
13
|
|
16
14
|
let(:method) do
|
17
|
-
->(
|
15
|
+
->(*) { 'token-value' }
|
18
16
|
end
|
19
17
|
|
20
18
|
it 'accepts anything that responds to #call' do
|
@@ -96,19 +94,47 @@ module Doorkeeper
|
|
96
94
|
end
|
97
95
|
|
98
96
|
describe :authenticate do
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
97
|
+
context 'refresh tokens are disabled (default)' do
|
98
|
+
context 'refresh tokens are enabled' do
|
99
|
+
it 'does not revoke previous refresh_token if token was found' do
|
100
|
+
token = ->(_r) { 'token' }
|
101
|
+
expect(
|
102
|
+
AccessToken
|
103
|
+
).to receive(:by_token).with('token').and_return(token)
|
104
|
+
expect(token).not_to receive(:revoke_previous_refresh_token!)
|
105
|
+
Token.authenticate double, token
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'calls the finder if token was returned' do
|
110
|
+
token = ->(_r) { 'token' }
|
111
|
+
expect(AccessToken).to receive(:by_token).with('token')
|
112
|
+
Token.authenticate double, token
|
113
|
+
end
|
103
114
|
end
|
104
115
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
116
|
+
context 'refresh tokens are enabled' do
|
117
|
+
before do
|
118
|
+
Doorkeeper.configure do
|
119
|
+
orm DOORKEEPER_ORM
|
120
|
+
use_refresh_token
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'revokes previous refresh_token if token was found' do
|
125
|
+
token = ->(_r) { 'token' }
|
126
|
+
expect(
|
127
|
+
AccessToken
|
128
|
+
).to receive(:by_token).with('token').and_return(token)
|
129
|
+
expect(token).to receive(:revoke_previous_refresh_token!)
|
130
|
+
Token.authenticate double, token
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'calls the finder if token was returned' do
|
134
|
+
token = ->(_r) { 'token' }
|
135
|
+
expect(AccessToken).to receive(:by_token).with('token')
|
136
|
+
Token.authenticate double, token
|
137
|
+
end
|
112
138
|
end
|
113
139
|
end
|
114
140
|
end
|
data/spec/lib/server_spec.rb
CHANGED
@@ -22,9 +22,9 @@ describe Doorkeeper::Server do
|
|
22
22
|
|
23
23
|
context 'when only Authorization Code strategy is enabled' do
|
24
24
|
before do
|
25
|
-
allow(Doorkeeper.configuration)
|
26
|
-
to receive(:grant_flows)
|
27
|
-
and_return(['authorization_code'])
|
25
|
+
allow(Doorkeeper.configuration)
|
26
|
+
.to receive(:grant_flows)
|
27
|
+
.and_return(['authorization_code'])
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'raises error when using the disabled Implicit strategy' do
|
@@ -46,10 +46,10 @@ describe Doorkeeper::Server do
|
|
46
46
|
subject.authorization_request :code
|
47
47
|
end
|
48
48
|
|
49
|
-
it 'builds the request with
|
50
|
-
allow(Doorkeeper.configuration)
|
51
|
-
to receive(:authorization_response_types)
|
52
|
-
and_return(['id_token token'])
|
49
|
+
it 'builds the request with composite strategy name' do
|
50
|
+
allow(Doorkeeper.configuration)
|
51
|
+
.to receive(:authorization_response_types)
|
52
|
+
.and_return(['id_token token'])
|
53
53
|
|
54
54
|
stub_const 'Doorkeeper::Request::IdTokenToken', fake_class
|
55
55
|
expect(fake_class).to receive(:new).with(subject)
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Doorkeeper::StaleRecordsCleaner do
|
6
|
+
let(:cleaner) { described_class.new(model) }
|
7
|
+
let(:models_by_name) do
|
8
|
+
{
|
9
|
+
access_token: Doorkeeper::AccessToken,
|
10
|
+
access_grant: Doorkeeper::AccessGrant
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when ORM has no cleaner class' do
|
15
|
+
it 'raises an error' do
|
16
|
+
allow_any_instance_of(Doorkeeper::Config).to receive(:orm).and_return('hibernate')
|
17
|
+
|
18
|
+
expect do
|
19
|
+
described_class.for(Doorkeeper::AccessToken)
|
20
|
+
end.to raise_error(Doorkeeper::Errors::NoOrmCleaner, /has no cleaner/)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
%i[access_token access_grant].each do |model_name|
|
25
|
+
context "(#{model_name})" do
|
26
|
+
let(:model) { models_by_name.fetch(model_name) }
|
27
|
+
|
28
|
+
describe '#clean_revoked' do
|
29
|
+
subject { cleaner.clean_revoked }
|
30
|
+
|
31
|
+
context 'with revoked record' do
|
32
|
+
before do
|
33
|
+
FactoryBot.create model_name, revoked_at: Time.current - 1.minute
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'removes the record' do
|
37
|
+
expect { subject }.to change { model.count }.to(0)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'with record revoked in the future' do
|
42
|
+
before do
|
43
|
+
FactoryBot.create model_name, revoked_at: Time.current + 1.minute
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'keeps the record' do
|
47
|
+
expect { subject }.not_to(change { model.count })
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'with unrevoked record' do
|
52
|
+
before do
|
53
|
+
FactoryBot.create model_name, revoked_at: nil
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'keeps the record' do
|
57
|
+
expect { subject }.not_to(change { model.count })
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#clean_expired' do
|
63
|
+
subject { cleaner.clean_expired(ttl) }
|
64
|
+
let(:ttl) { 500 }
|
65
|
+
let(:expiry_border) { ttl.seconds.ago }
|
66
|
+
|
67
|
+
context 'with record that is expired' do
|
68
|
+
before do
|
69
|
+
FactoryBot.create model_name, created_at: expiry_border - 1.minute
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'removes the record' do
|
73
|
+
expect { subject }.to change { model.count }.to(0)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'with record that is not expired' do
|
78
|
+
before do
|
79
|
+
FactoryBot.create model_name, created_at: expiry_border + 1.minute
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'keeps the record' do
|
83
|
+
expect { subject }.not_to(change { model.count })
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Doorkeeper::AccessGrant do
|
4
4
|
subject { FactoryBot.build(:access_grant) }
|
@@ -33,4 +33,47 @@ describe Doorkeeper::AccessGrant do
|
|
33
33
|
expect(subject).not_to be_valid
|
34
34
|
end
|
35
35
|
end
|
36
|
+
|
37
|
+
describe '.revoke_all_for' do
|
38
|
+
let(:resource_owner) { double(id: 100) }
|
39
|
+
let(:application) { FactoryBot.create :application }
|
40
|
+
let(:default_attributes) do
|
41
|
+
{
|
42
|
+
application: application,
|
43
|
+
resource_owner_id: resource_owner.id
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'revokes all tokens for given application and resource owner' do
|
48
|
+
FactoryBot.create :access_grant, default_attributes
|
49
|
+
|
50
|
+
described_class.revoke_all_for(application.id, resource_owner)
|
51
|
+
|
52
|
+
described_class.all.each do |token|
|
53
|
+
expect(token).to be_revoked
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'matches application' do
|
58
|
+
access_grant_for_different_app = FactoryBot.create(
|
59
|
+
:access_grant,
|
60
|
+
default_attributes.merge(application: FactoryBot.create(:application))
|
61
|
+
)
|
62
|
+
|
63
|
+
described_class.revoke_all_for(application.id, resource_owner)
|
64
|
+
|
65
|
+
expect(access_grant_for_different_app.reload).not_to be_revoked
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'matches resource owner' do
|
69
|
+
access_grant_for_different_owner = FactoryBot.create(
|
70
|
+
:access_grant,
|
71
|
+
default_attributes.merge(resource_owner_id: 90)
|
72
|
+
)
|
73
|
+
|
74
|
+
described_class.revoke_all_for application.id, resource_owner
|
75
|
+
|
76
|
+
expect(access_grant_for_different_owner.reload).not_to be_revoked
|
77
|
+
end
|
78
|
+
end
|
36
79
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
module Doorkeeper
|
4
4
|
describe AccessToken do
|
@@ -13,8 +13,7 @@ module Doorkeeper
|
|
13
13
|
end
|
14
14
|
|
15
15
|
module CustomGeneratorArgs
|
16
|
-
def self.generate
|
17
|
-
end
|
16
|
+
def self.generate; end
|
18
17
|
end
|
19
18
|
|
20
19
|
describe :generate_token do
|
@@ -42,7 +41,7 @@ module Doorkeeper
|
|
42
41
|
end
|
43
42
|
|
44
43
|
token = FactoryBot.create :access_token
|
45
|
-
expect(token.token).to match(
|
44
|
+
expect(token.token).to match(/custom_generator_token_\d+/)
|
46
45
|
end
|
47
46
|
|
48
47
|
it 'allows the custom generator to access the application details' do
|
@@ -62,7 +61,7 @@ module Doorkeeper
|
|
62
61
|
end
|
63
62
|
|
64
63
|
token = FactoryBot.create :access_token
|
65
|
-
expect(token.token).to match(
|
64
|
+
expect(token.token).to match(/custom_generator_token_Application \d+/)
|
66
65
|
end
|
67
66
|
|
68
67
|
it 'allows the custom generator to access the scopes' do
|
@@ -144,7 +143,7 @@ module Doorkeeper
|
|
144
143
|
end
|
145
144
|
|
146
145
|
module CustomGeneratorArgs
|
147
|
-
def self.generate(
|
146
|
+
def self.generate(_opts = {})
|
148
147
|
raise LoadError, 'custom behaviour'
|
149
148
|
end
|
150
149
|
end
|
@@ -214,11 +213,9 @@ module Doorkeeper
|
|
214
213
|
end
|
215
214
|
|
216
215
|
describe '#same_credential?' do
|
217
|
-
|
218
216
|
context 'with default parameters' do
|
219
|
-
|
220
217
|
let(:resource_owner_id) { 100 }
|
221
|
-
let(:application)
|
218
|
+
let(:application) { FactoryBot.create :application }
|
222
219
|
let(:default_attributes) do
|
223
220
|
{ application: application, resource_owner_id: resource_owner_id }
|
224
221
|
end
|
@@ -233,7 +230,11 @@ module Doorkeeper
|
|
233
230
|
|
234
231
|
context 'the second token has same owner and different app' do
|
235
232
|
let(:other_application) { FactoryBot.create :application }
|
236
|
-
let(:access_token2)
|
233
|
+
let(:access_token2) do
|
234
|
+
FactoryBot.create :access_token,
|
235
|
+
application: other_application,
|
236
|
+
resource_owner_id: resource_owner_id
|
237
|
+
end
|
237
238
|
|
238
239
|
it 'fail' do
|
239
240
|
expect(access_token1.same_credential?(access_token2)).to be_falsey
|
@@ -241,9 +242,10 @@ module Doorkeeper
|
|
241
242
|
end
|
242
243
|
|
243
244
|
context 'the second token has different owner and different app' do
|
244
|
-
|
245
245
|
let(:other_application) { FactoryBot.create :application }
|
246
|
-
let(:access_token2)
|
246
|
+
let(:access_token2) do
|
247
|
+
FactoryBot.create :access_token, application: other_application, resource_owner_id: 42
|
248
|
+
end
|
247
249
|
|
248
250
|
it 'fail' do
|
249
251
|
expect(access_token1.same_credential?(access_token2)).to be_falsey
|
@@ -251,7 +253,9 @@ module Doorkeeper
|
|
251
253
|
end
|
252
254
|
|
253
255
|
context 'the second token has different owner and same app' do
|
254
|
-
let(:access_token2)
|
256
|
+
let(:access_token2) do
|
257
|
+
FactoryBot.create :access_token, application: application, resource_owner_id: 42
|
258
|
+
end
|
255
259
|
|
256
260
|
it 'fail' do
|
257
261
|
expect(access_token1.same_credential?(access_token2)).to be_falsey
|
@@ -306,15 +310,25 @@ module Doorkeeper
|
|
306
310
|
end
|
307
311
|
|
308
312
|
it 'matches application' do
|
309
|
-
|
313
|
+
access_token_for_different_app = FactoryBot.create(
|
314
|
+
:access_token,
|
315
|
+
default_attributes.merge(application: FactoryBot.create(:application))
|
316
|
+
)
|
317
|
+
|
310
318
|
AccessToken.revoke_all_for application.id, resource_owner
|
311
|
-
|
319
|
+
|
320
|
+
expect(access_token_for_different_app.reload).not_to be_revoked
|
312
321
|
end
|
313
322
|
|
314
323
|
it 'matches resource owner' do
|
315
|
-
FactoryBot.create
|
324
|
+
access_token_for_different_owner = FactoryBot.create(
|
325
|
+
:access_token,
|
326
|
+
default_attributes.merge(resource_owner_id: 90)
|
327
|
+
)
|
328
|
+
|
316
329
|
AccessToken.revoke_all_for application.id, resource_owner
|
317
|
-
|
330
|
+
|
331
|
+
expect(access_token_for_different_owner.reload).not_to be_revoked
|
318
332
|
end
|
319
333
|
end
|
320
334
|
|
@@ -330,6 +344,10 @@ module Doorkeeper
|
|
330
344
|
}
|
331
345
|
end
|
332
346
|
|
347
|
+
before do
|
348
|
+
default_scopes_exist(*scopes.all)
|
349
|
+
end
|
350
|
+
|
333
351
|
it 'returns only one token' do
|
334
352
|
token = FactoryBot.create :access_token, default_attributes
|
335
353
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
@@ -355,37 +373,45 @@ module Doorkeeper
|
|
355
373
|
expect(last_token).to be_nil
|
356
374
|
end
|
357
375
|
|
358
|
-
it
|
376
|
+
it "excludes tokens with a different application" do
|
359
377
|
FactoryBot.create :access_token, default_attributes.merge(application: FactoryBot.create(:application))
|
360
378
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
361
379
|
expect(last_token).to be_nil
|
362
380
|
end
|
363
381
|
|
364
|
-
it
|
382
|
+
it "excludes tokens with a different resource owner" do
|
365
383
|
FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: 2)
|
366
384
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
367
385
|
expect(last_token).to be_nil
|
368
386
|
end
|
369
387
|
|
370
|
-
it
|
388
|
+
it "excludes tokens with fewer scopes" do
|
371
389
|
FactoryBot.create :access_token, default_attributes.merge(scopes: 'public')
|
372
390
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
373
391
|
expect(last_token).to be_nil
|
374
392
|
end
|
375
393
|
|
376
|
-
it '
|
394
|
+
it 'excludes tokens with different scopes' do
|
377
395
|
FactoryBot.create :access_token, default_attributes.merge(scopes: 'public email')
|
378
396
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
379
397
|
expect(last_token).to be_nil
|
380
398
|
end
|
381
399
|
|
382
|
-
it '
|
400
|
+
it 'excludes tokens with additional scopes' do
|
383
401
|
FactoryBot.create :access_token, default_attributes.merge(scopes: 'public write email')
|
384
402
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
385
403
|
expect(last_token).to be_nil
|
386
404
|
end
|
387
405
|
|
388
|
-
it '
|
406
|
+
it 'excludes tokens with scopes that are not present in server scopes' do
|
407
|
+
FactoryBot.create :access_token, default_attributes.merge(
|
408
|
+
application: application, scopes: 'public read'
|
409
|
+
)
|
410
|
+
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
411
|
+
expect(last_token).to be_nil
|
412
|
+
end
|
413
|
+
|
414
|
+
it 'excludes tokens with scopes that are not present in application scopes' do
|
389
415
|
application = FactoryBot.create :application, scopes: "private read"
|
390
416
|
FactoryBot.create :access_token, default_attributes.merge(
|
391
417
|
application: application
|
@@ -394,25 +420,47 @@ module Doorkeeper
|
|
394
420
|
expect(last_token).to be_nil
|
395
421
|
end
|
396
422
|
|
397
|
-
it '
|
423
|
+
it 'does not match token if empty scope requested and token/app scopes present' do
|
424
|
+
application = FactoryBot.create :application, scopes: "sample:scope"
|
425
|
+
app_params = {
|
426
|
+
application_id: application.id, scopes: "sample:scope",
|
427
|
+
resource_owner_id: 100
|
428
|
+
}
|
429
|
+
FactoryBot.create :access_token, app_params
|
430
|
+
empty_scopes = Doorkeeper::OAuth::Scopes.from_string("")
|
431
|
+
last_token = AccessToken.matching_token_for(application, 100, empty_scopes)
|
432
|
+
expect(last_token).to be_nil
|
433
|
+
end
|
434
|
+
|
435
|
+
it 'matches token if empty scope requested and no token scopes present' do
|
436
|
+
empty_scopes = Doorkeeper::OAuth::Scopes.from_string("")
|
437
|
+
token = FactoryBot.create :access_token, default_attributes.merge(scopes: empty_scopes)
|
438
|
+
last_token = AccessToken.matching_token_for(application, 100, empty_scopes)
|
439
|
+
expect(last_token).to eq(token)
|
440
|
+
end
|
441
|
+
|
442
|
+
it 'returns the last matching token' do
|
398
443
|
FactoryBot.create :access_token, default_attributes.merge(created_at: 1.day.ago)
|
399
|
-
|
444
|
+
matching_token = FactoryBot.create :access_token, default_attributes
|
445
|
+
FactoryBot.create :access_token, default_attributes.merge(scopes: 'public')
|
446
|
+
|
400
447
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
401
|
-
expect(last_token).to eq(
|
448
|
+
expect(last_token).to eq(matching_token)
|
402
449
|
end
|
450
|
+
end
|
403
451
|
|
404
|
-
|
405
|
-
|
452
|
+
describe "#as_json" do
|
453
|
+
it "returns as_json hash" do
|
454
|
+
token = FactoryBot.create :access_token
|
406
455
|
token_hash = {
|
407
456
|
resource_owner_id: token.resource_owner_id,
|
408
|
-
|
409
|
-
|
457
|
+
scope: token.scopes,
|
458
|
+
expires_in: token.expires_in_seconds,
|
410
459
|
application: { uid: token.application.uid },
|
411
|
-
created_at: token.created_at.to_i
|
460
|
+
created_at: token.created_at.to_i
|
412
461
|
}
|
413
462
|
expect(token.as_json).to eq token_hash
|
414
463
|
end
|
415
464
|
end
|
416
|
-
|
417
465
|
end
|
418
466
|
end
|