doorkeeper 4.2.5 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE.md +25 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
- data/.gitignore +2 -1
- data/.gitlab-ci.yml +16 -0
- data/.hound.yml +2 -13
- data/.rubocop.yml +17 -0
- data/.travis.yml +19 -4
- data/Appraisals +8 -4
- data/CODE_OF_CONDUCT.md +46 -0
- data/Gemfile +1 -1
- data/NEWS.md +115 -0
- data/README.md +175 -39
- data/RELEASING.md +5 -12
- data/Rakefile +6 -0
- data/SECURITY.md +15 -0
- data/UPGRADE.md +2 -0
- data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +2 -5
- data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
- data/app/controllers/doorkeeper/applications_controller.rb +47 -13
- data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +19 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +24 -17
- data/app/helpers/doorkeeper/dashboard_helper.rb +8 -6
- data/app/validators/redirect_uri_validator.rb +13 -2
- data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
- data/app/views/doorkeeper/applications/_form.html.erb +31 -19
- data/app/views/doorkeeper/applications/edit.html.erb +1 -1
- data/app/views/doorkeeper/applications/index.html.erb +18 -6
- data/app/views/doorkeeper/applications/new.html.erb +1 -1
- data/app/views/doorkeeper/applications/show.html.erb +8 -5
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +5 -1
- data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
- data/config/locales/en.yml +19 -6
- data/doorkeeper.gemspec +20 -20
- data/gemfiles/rails_4_2.gemfile +6 -4
- data/gemfiles/rails_5_0.gemfile +4 -4
- data/gemfiles/rails_5_1.gemfile +6 -7
- data/gemfiles/rails_5_2.gemfile +12 -0
- data/gemfiles/rails_master.gemfile +17 -0
- data/lib/doorkeeper/config.rb +123 -71
- data/lib/doorkeeper/engine.rb +7 -3
- data/lib/doorkeeper/errors.rb +20 -5
- data/lib/doorkeeper/grape/helpers.rb +14 -9
- data/lib/doorkeeper/helpers/controller.rb +16 -22
- data/lib/doorkeeper/models/access_grant_mixin.rb +67 -23
- data/lib/doorkeeper/models/access_token_mixin.rb +54 -55
- data/lib/doorkeeper/models/application_mixin.rb +16 -30
- data/lib/doorkeeper/models/concerns/expirable.rb +7 -5
- data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
- data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/code.rb +31 -8
- data/lib/doorkeeper/oauth/authorization/context.rb +15 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +46 -20
- data/lib/doorkeeper/oauth/authorization_code_request.rb +33 -3
- data/lib/doorkeeper/oauth/base_request.rb +23 -7
- data/lib/doorkeeper/oauth/client/credentials.rb +6 -4
- data/lib/doorkeeper/oauth/client.rb +2 -4
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -1
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -3
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -6
- data/lib/doorkeeper/oauth/client_credentials_request.rb +0 -4
- data/lib/doorkeeper/oauth/error.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +11 -4
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +15 -0
- data/lib/doorkeeper/oauth/invalid_token_response.rb +3 -4
- data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -4
- data/lib/doorkeeper/oauth/pre_authorization.rb +45 -13
- data/lib/doorkeeper/oauth/refresh_token_request.rb +7 -1
- data/lib/doorkeeper/oauth/scopes.rb +19 -9
- data/lib/doorkeeper/oauth/token.rb +6 -3
- data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
- data/lib/doorkeeper/oauth/token_response.rb +4 -2
- data/lib/doorkeeper/oauth.rb +13 -0
- data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
- data/lib/doorkeeper/orm/active_record/access_token.rb +21 -20
- data/lib/doorkeeper/orm/active_record/application.rb +45 -0
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
- data/lib/doorkeeper/orm/active_record.rb +21 -8
- data/lib/doorkeeper/rails/helpers.rb +7 -10
- data/lib/doorkeeper/rails/routes.rb +21 -7
- 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 +0 -2
- data/lib/doorkeeper/request/client_credentials.rb +0 -2
- data/lib/doorkeeper/request/code.rb +0 -2
- data/lib/doorkeeper/request/password.rb +1 -13
- data/lib/doorkeeper/request/refresh_token.rb +0 -2
- data/lib/doorkeeper/request/token.rb +0 -2
- data/lib/doorkeeper/request.rb +29 -30
- data/lib/doorkeeper/validations.rb +3 -2
- data/lib/doorkeeper/version.rb +14 -1
- data/lib/doorkeeper.rb +21 -17
- data/lib/generators/doorkeeper/application_owner_generator.rb +26 -12
- 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 +26 -9
- data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +31 -20
- data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
- data/lib/generators/doorkeeper/templates/{add_owner_to_application_migration.rb → add_owner_to_application_migration.rb.erb} +1 -1
- data/lib/generators/doorkeeper/templates/{add_previous_refresh_token_to_access_tokens.rb → add_previous_refresh_token_to_access_tokens.rb.erb} +1 -1
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +104 -12
- data/lib/generators/doorkeeper/templates/{migration.rb → migration.rb.erb} +2 -1
- 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 +141 -17
- data/spec/controllers/authorizations_controller_spec.rb +304 -27
- data/spec/controllers/protected_resources_controller_spec.rb +44 -35
- data/spec/controllers/token_info_controller_spec.rb +17 -21
- data/spec/controllers/tokens_controller_spec.rb +201 -17
- data/spec/dummy/app/assets/config/manifest.js +2 -0
- data/spec/dummy/config/environments/test.rb +4 -5
- data/spec/dummy/config/initializers/doorkeeper.rb +23 -2
- data/spec/dummy/config/initializers/{active_record_belongs_to_required_by_default.rb → new_framework_defaults.rb} +5 -1
- data/spec/dummy/config/initializers/secret_token.rb +0 -1
- data/spec/dummy/config/routes.rb +3 -42
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -1
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +3 -1
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +3 -1
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +13 -0
- data/spec/dummy/db/schema.rb +38 -37
- data/spec/factories.rb +1 -1
- data/spec/generators/application_owner_generator_spec.rb +25 -6
- data/spec/generators/confidential_applications_generator_spec.rb +45 -0
- data/spec/generators/install_generator_spec.rb +1 -1
- data/spec/generators/migration_generator_spec.rb +25 -4
- data/spec/generators/pkce_generator_spec.rb +43 -0
- data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
- data/spec/generators/views_generator_spec.rb +1 -1
- data/spec/grape/grape_integration_spec.rb +135 -0
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +2 -2
- data/spec/lib/config_spec.rb +199 -22
- data/spec/lib/doorkeeper_spec.rb +1 -126
- data/spec/lib/models/expirable_spec.rb +0 -4
- data/spec/lib/models/revocable_spec.rb +2 -4
- 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 +63 -13
- data/spec/lib/oauth/base_request_spec.rb +43 -10
- data/spec/lib/oauth/base_response_spec.rb +1 -1
- data/spec/lib/oauth/client/credentials_spec.rb +5 -5
- data/spec/lib/oauth/client_credentials/creator_spec.rb +6 -2
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +26 -7
- data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -3
- data/spec/lib/oauth/client_credentials_integration_spec.rb +2 -2
- data/spec/lib/oauth/client_credentials_request_spec.rb +4 -5
- data/spec/lib/oauth/client_spec.rb +0 -3
- data/spec/lib/oauth/code_request_spec.rb +5 -5
- data/spec/lib/oauth/error_response_spec.rb +0 -3
- data/spec/lib/oauth/error_spec.rb +1 -3
- data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -3
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -3
- data/spec/lib/oauth/invalid_token_response_spec.rb +2 -5
- data/spec/lib/oauth/password_access_token_request_spec.rb +46 -5
- data/spec/lib/oauth/pre_authorization_spec.rb +40 -6
- data/spec/lib/oauth/refresh_token_request_spec.rb +30 -14
- data/spec/lib/oauth/scopes_spec.rb +28 -4
- data/spec/lib/oauth/token_request_spec.rb +10 -13
- data/spec/lib/oauth/token_response_spec.rb +0 -1
- data/spec/lib/oauth/token_spec.rb +37 -14
- data/spec/lib/orm/active_record/stale_records_cleaner_spec.rb +79 -0
- data/spec/lib/request/strategy_spec.rb +0 -1
- data/spec/lib/server_spec.rb +10 -0
- data/spec/models/doorkeeper/access_grant_spec.rb +45 -2
- data/spec/models/doorkeeper/access_token_spec.rb +132 -64
- data/spec/models/doorkeeper/application_spec.rb +114 -23
- data/spec/requests/applications/applications_request_spec.rb +139 -6
- data/spec/requests/applications/authorized_applications_spec.rb +1 -1
- data/spec/requests/endpoints/authorization_spec.rb +1 -1
- data/spec/requests/endpoints/token_spec.rb +15 -6
- data/spec/requests/flows/authorization_code_errors_spec.rb +12 -2
- data/spec/requests/flows/authorization_code_spec.rb +199 -2
- data/spec/requests/flows/client_credentials_spec.rb +73 -5
- 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 +160 -24
- data/spec/requests/flows/refresh_token_spec.rb +6 -6
- data/spec/requests/flows/revoke_token_spec.rb +26 -26
- data/spec/requests/flows/skip_authorization_spec.rb +16 -11
- data/spec/requests/protected_resources/metal_spec.rb +2 -2
- data/spec/requests/protected_resources/private_api_spec.rb +2 -2
- data/spec/routing/custom_controller_routes_spec.rb +63 -7
- data/spec/routing/default_routes_spec.rb +6 -2
- data/spec/routing/scoped_routes_spec.rb +16 -2
- data/spec/spec_helper.rb +54 -3
- data/spec/spec_helper_integration.rb +2 -64
- data/spec/support/dependencies/factory_bot.rb +2 -0
- data/spec/support/doorkeeper_rspec.rb +19 -0
- data/spec/support/helpers/access_token_request_helper.rb +1 -1
- data/spec/support/helpers/authorization_request_helper.rb +4 -4
- data/spec/support/helpers/model_helper.rb +9 -4
- data/spec/support/helpers/request_spec_helper.rb +18 -6
- data/spec/support/helpers/url_helper.rb +15 -10
- data/spec/support/http_method_shim.rb +12 -16
- data/spec/support/shared/controllers_shared_context.rb +2 -6
- data/spec/support/shared/models_shared_examples.rb +4 -4
- data/spec/validators/redirect_uri_validator_spec.rb +58 -7
- data/spec/version/version_spec.rb +15 -0
- data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
- metadata +75 -33
- data/spec/controllers/application_metal_controller.rb +0 -10
- data/spec/support/dependencies/factory_girl.rb +0 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
module Doorkeeper
|
|
4
4
|
describe AccessToken do
|
|
5
|
-
subject {
|
|
5
|
+
subject { FactoryBot.build(:access_token) }
|
|
6
6
|
|
|
7
7
|
it { expect(subject).to be_valid }
|
|
8
8
|
|
|
@@ -19,9 +19,9 @@ module Doorkeeper
|
|
|
19
19
|
|
|
20
20
|
describe :generate_token do
|
|
21
21
|
it 'generates a token using the default method' do
|
|
22
|
-
|
|
22
|
+
FactoryBot.create :access_token
|
|
23
23
|
|
|
24
|
-
token =
|
|
24
|
+
token = FactoryBot.create :access_token
|
|
25
25
|
expect(token.token).to be_a(String)
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -41,7 +41,7 @@ module Doorkeeper
|
|
|
41
41
|
access_token_generator "Doorkeeper::CustomGeneratorArgs"
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
token =
|
|
44
|
+
token = FactoryBot.create :access_token
|
|
45
45
|
expect(token.token).to match(%r{custom_generator_token_\d+})
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -61,7 +61,7 @@ module Doorkeeper
|
|
|
61
61
|
access_token_generator "Doorkeeper::CustomGeneratorArgs"
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
token =
|
|
64
|
+
token = FactoryBot.create :access_token
|
|
65
65
|
expect(token.token).to match(%r{custom_generator_token_Application \d+})
|
|
66
66
|
end
|
|
67
67
|
|
|
@@ -81,7 +81,7 @@ module Doorkeeper
|
|
|
81
81
|
access_token_generator "Doorkeeper::CustomGeneratorArgs"
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
-
token =
|
|
84
|
+
token = FactoryBot.create :access_token, scopes: 'public write'
|
|
85
85
|
|
|
86
86
|
expect(token.token).to eq 'custom_generator_token_2_public write'
|
|
87
87
|
end
|
|
@@ -102,7 +102,7 @@ module Doorkeeper
|
|
|
102
102
|
access_token_generator "Doorkeeper::CustomGeneratorArgs"
|
|
103
103
|
end
|
|
104
104
|
|
|
105
|
-
token =
|
|
105
|
+
token = FactoryBot.create :access_token
|
|
106
106
|
expect(token.token).to eq 'custom_generator_token_7200'
|
|
107
107
|
end
|
|
108
108
|
|
|
@@ -118,7 +118,7 @@ module Doorkeeper
|
|
|
118
118
|
access_token_generator "Doorkeeper::CustomGeneratorArgs"
|
|
119
119
|
end
|
|
120
120
|
|
|
121
|
-
token =
|
|
121
|
+
token = FactoryBot.create :access_token
|
|
122
122
|
created_at = token.created_at
|
|
123
123
|
expect(token.token).to eq "custom_generator_token_#{created_at.to_i}"
|
|
124
124
|
end
|
|
@@ -132,8 +132,31 @@ module Doorkeeper
|
|
|
132
132
|
access_token_generator "Doorkeeper::NoGenerate"
|
|
133
133
|
end
|
|
134
134
|
|
|
135
|
-
expect {
|
|
136
|
-
raise_error(Doorkeeper::Errors::UnableToGenerateToken)
|
|
135
|
+
expect { FactoryBot.create :access_token }.to(
|
|
136
|
+
raise_error(Doorkeeper::Errors::UnableToGenerateToken)
|
|
137
|
+
)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it 'raises original error if something went wrong in custom generator' do
|
|
141
|
+
eigenclass = class << CustomGeneratorArgs; self; end
|
|
142
|
+
eigenclass.class_eval do
|
|
143
|
+
remove_method :generate
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
module CustomGeneratorArgs
|
|
147
|
+
def self.generate(_opts = {})
|
|
148
|
+
raise LoadError, 'custom behaviour'
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
Doorkeeper.configure do
|
|
153
|
+
orm DOORKEEPER_ORM
|
|
154
|
+
access_token_generator "Doorkeeper::CustomGeneratorArgs"
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
expect { FactoryBot.create :access_token }.to(
|
|
158
|
+
raise_error(LoadError)
|
|
159
|
+
)
|
|
137
160
|
end
|
|
138
161
|
|
|
139
162
|
it 'raises an error if the custom object does not exist' do
|
|
@@ -142,32 +165,33 @@ module Doorkeeper
|
|
|
142
165
|
access_token_generator "Doorkeeper::NotReal"
|
|
143
166
|
end
|
|
144
167
|
|
|
145
|
-
expect {
|
|
146
|
-
raise_error(Doorkeeper::Errors::TokenGeneratorNotFound)
|
|
168
|
+
expect { FactoryBot.create :access_token }.to(
|
|
169
|
+
raise_error(Doorkeeper::Errors::TokenGeneratorNotFound, /NotReal/)
|
|
170
|
+
)
|
|
147
171
|
end
|
|
148
172
|
end
|
|
149
173
|
|
|
150
174
|
describe :refresh_token do
|
|
151
175
|
it 'has empty refresh token if it was not required' do
|
|
152
|
-
token =
|
|
176
|
+
token = FactoryBot.create :access_token
|
|
153
177
|
expect(token.refresh_token).to be_nil
|
|
154
178
|
end
|
|
155
179
|
|
|
156
180
|
it 'generates a refresh token if it was requested' do
|
|
157
|
-
token =
|
|
181
|
+
token = FactoryBot.create :access_token, use_refresh_token: true
|
|
158
182
|
expect(token.refresh_token).not_to be_nil
|
|
159
183
|
end
|
|
160
184
|
|
|
161
185
|
it 'is not valid if token exists' do
|
|
162
|
-
token1 =
|
|
163
|
-
token2 =
|
|
186
|
+
token1 = FactoryBot.create :access_token, use_refresh_token: true
|
|
187
|
+
token2 = FactoryBot.create :access_token, use_refresh_token: true
|
|
164
188
|
token2.refresh_token = token1.refresh_token
|
|
165
189
|
expect(token2).not_to be_valid
|
|
166
190
|
end
|
|
167
191
|
|
|
168
192
|
it 'expects database to raise an error if refresh tokens are the same' do
|
|
169
|
-
token1 =
|
|
170
|
-
token2 =
|
|
193
|
+
token1 = FactoryBot.create :access_token, use_refresh_token: true
|
|
194
|
+
token2 = FactoryBot.create :access_token, use_refresh_token: true
|
|
171
195
|
expect do
|
|
172
196
|
token2.refresh_token = token1.refresh_token
|
|
173
197
|
token2.save(validate: false)
|
|
@@ -194,22 +218,22 @@ module Doorkeeper
|
|
|
194
218
|
context 'with default parameters' do
|
|
195
219
|
|
|
196
220
|
let(:resource_owner_id) { 100 }
|
|
197
|
-
let(:application)
|
|
221
|
+
let(:application) { FactoryBot.create :application }
|
|
198
222
|
let(:default_attributes) do
|
|
199
223
|
{ application: application, resource_owner_id: resource_owner_id }
|
|
200
224
|
end
|
|
201
|
-
let(:access_token1) {
|
|
225
|
+
let(:access_token1) { FactoryBot.create :access_token, default_attributes }
|
|
202
226
|
|
|
203
227
|
context 'the second token has the same owner and same app' do
|
|
204
|
-
let(:access_token2) {
|
|
228
|
+
let(:access_token2) { FactoryBot.create :access_token, default_attributes }
|
|
205
229
|
it 'success' do
|
|
206
230
|
expect(access_token1.same_credential?(access_token2)).to be_truthy
|
|
207
231
|
end
|
|
208
232
|
end
|
|
209
233
|
|
|
210
234
|
context 'the second token has same owner and different app' do
|
|
211
|
-
let(:other_application) {
|
|
212
|
-
let(:access_token2) {
|
|
235
|
+
let(:other_application) { FactoryBot.create :application }
|
|
236
|
+
let(:access_token2) { FactoryBot.create :access_token, application: other_application, resource_owner_id: resource_owner_id }
|
|
213
237
|
|
|
214
238
|
it 'fail' do
|
|
215
239
|
expect(access_token1.same_credential?(access_token2)).to be_falsey
|
|
@@ -218,8 +242,8 @@ module Doorkeeper
|
|
|
218
242
|
|
|
219
243
|
context 'the second token has different owner and different app' do
|
|
220
244
|
|
|
221
|
-
let(:other_application) {
|
|
222
|
-
let(:access_token2) {
|
|
245
|
+
let(:other_application) { FactoryBot.create :application }
|
|
246
|
+
let(:access_token2) { FactoryBot.create :access_token, application: other_application, resource_owner_id: 42 }
|
|
223
247
|
|
|
224
248
|
it 'fail' do
|
|
225
249
|
expect(access_token1.same_credential?(access_token2)).to be_falsey
|
|
@@ -227,7 +251,7 @@ module Doorkeeper
|
|
|
227
251
|
end
|
|
228
252
|
|
|
229
253
|
context 'the second token has different owner and same app' do
|
|
230
|
-
let(:access_token2) {
|
|
254
|
+
let(:access_token2) { FactoryBot.create :access_token, application: application, resource_owner_id: 42 }
|
|
231
255
|
|
|
232
256
|
it 'fail' do
|
|
233
257
|
expect(access_token1.same_credential?(access_token2)).to be_falsey
|
|
@@ -238,7 +262,7 @@ module Doorkeeper
|
|
|
238
262
|
|
|
239
263
|
describe '#acceptable?' do
|
|
240
264
|
context 'a token that is not accessible' do
|
|
241
|
-
let(:token) {
|
|
265
|
+
let(:token) { FactoryBot.create(:access_token, created_at: 6.hours.ago) }
|
|
242
266
|
|
|
243
267
|
it 'should return false' do
|
|
244
268
|
expect(token.acceptable?(nil)).to be false
|
|
@@ -246,7 +270,7 @@ module Doorkeeper
|
|
|
246
270
|
end
|
|
247
271
|
|
|
248
272
|
context 'a token that has the incorrect scopes' do
|
|
249
|
-
let(:token) {
|
|
273
|
+
let(:token) { FactoryBot.create(:access_token) }
|
|
250
274
|
|
|
251
275
|
it 'should return false' do
|
|
252
276
|
expect(token.acceptable?(['public'])).to be false
|
|
@@ -255,7 +279,7 @@ module Doorkeeper
|
|
|
255
279
|
|
|
256
280
|
context 'a token is acceptable with the correct scopes' do
|
|
257
281
|
let(:token) do
|
|
258
|
-
token =
|
|
282
|
+
token = FactoryBot.create(:access_token)
|
|
259
283
|
token[:scopes] = 'public'
|
|
260
284
|
token
|
|
261
285
|
end
|
|
@@ -268,13 +292,13 @@ module Doorkeeper
|
|
|
268
292
|
|
|
269
293
|
describe '.revoke_all_for' do
|
|
270
294
|
let(:resource_owner) { double(id: 100) }
|
|
271
|
-
let(:application) {
|
|
295
|
+
let(:application) { FactoryBot.create :application }
|
|
272
296
|
let(:default_attributes) do
|
|
273
297
|
{ application: application, resource_owner_id: resource_owner.id }
|
|
274
298
|
end
|
|
275
299
|
|
|
276
300
|
it 'revokes all tokens for given application and resource owner' do
|
|
277
|
-
|
|
301
|
+
FactoryBot.create :access_token, default_attributes
|
|
278
302
|
AccessToken.revoke_all_for application.id, resource_owner
|
|
279
303
|
AccessToken.all.each do |token|
|
|
280
304
|
expect(token).to be_revoked
|
|
@@ -282,21 +306,31 @@ module Doorkeeper
|
|
|
282
306
|
end
|
|
283
307
|
|
|
284
308
|
it 'matches application' do
|
|
285
|
-
|
|
309
|
+
access_token_for_different_app = FactoryBot.create(
|
|
310
|
+
:access_token,
|
|
311
|
+
default_attributes.merge(application: FactoryBot.create(:application))
|
|
312
|
+
)
|
|
313
|
+
|
|
286
314
|
AccessToken.revoke_all_for application.id, resource_owner
|
|
287
|
-
|
|
315
|
+
|
|
316
|
+
expect(access_token_for_different_app.reload).not_to be_revoked
|
|
288
317
|
end
|
|
289
318
|
|
|
290
319
|
it 'matches resource owner' do
|
|
291
|
-
|
|
320
|
+
access_token_for_different_owner = FactoryBot.create(
|
|
321
|
+
:access_token,
|
|
322
|
+
default_attributes.merge(resource_owner_id: 90)
|
|
323
|
+
)
|
|
324
|
+
|
|
292
325
|
AccessToken.revoke_all_for application.id, resource_owner
|
|
293
|
-
|
|
326
|
+
|
|
327
|
+
expect(access_token_for_different_owner.reload).not_to be_revoked
|
|
294
328
|
end
|
|
295
329
|
end
|
|
296
330
|
|
|
297
331
|
describe '.matching_token_for' do
|
|
298
332
|
let(:resource_owner_id) { 100 }
|
|
299
|
-
let(:application) {
|
|
333
|
+
let(:application) { FactoryBot.create :application }
|
|
300
334
|
let(:scopes) { Doorkeeper::OAuth::Scopes.from_string('public write') }
|
|
301
335
|
let(:default_attributes) do
|
|
302
336
|
{
|
|
@@ -306,89 +340,123 @@ module Doorkeeper
|
|
|
306
340
|
}
|
|
307
341
|
end
|
|
308
342
|
|
|
343
|
+
before do
|
|
344
|
+
default_scopes_exist(*scopes.all)
|
|
345
|
+
end
|
|
346
|
+
|
|
309
347
|
it 'returns only one token' do
|
|
310
|
-
token =
|
|
348
|
+
token = FactoryBot.create :access_token, default_attributes
|
|
311
349
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
312
350
|
expect(last_token).to eq(token)
|
|
313
351
|
end
|
|
314
352
|
|
|
315
353
|
it 'accepts resource owner as object' do
|
|
316
354
|
resource_owner = double(to_key: true, id: 100)
|
|
317
|
-
token =
|
|
355
|
+
token = FactoryBot.create :access_token, default_attributes
|
|
318
356
|
last_token = AccessToken.matching_token_for(application, resource_owner, scopes)
|
|
319
357
|
expect(last_token).to eq(token)
|
|
320
358
|
end
|
|
321
359
|
|
|
322
360
|
it 'accepts nil as resource owner' do
|
|
323
|
-
token =
|
|
361
|
+
token = FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: nil)
|
|
324
362
|
last_token = AccessToken.matching_token_for(application, nil, scopes)
|
|
325
363
|
expect(last_token).to eq(token)
|
|
326
364
|
end
|
|
327
365
|
|
|
328
366
|
it 'excludes revoked tokens' do
|
|
329
|
-
|
|
367
|
+
FactoryBot.create :access_token, default_attributes.merge(revoked_at: 1.day.ago)
|
|
330
368
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
331
369
|
expect(last_token).to be_nil
|
|
332
370
|
end
|
|
333
371
|
|
|
334
|
-
it
|
|
335
|
-
|
|
372
|
+
it "excludes tokens with a different application" do
|
|
373
|
+
FactoryBot.create :access_token, default_attributes.merge(application: FactoryBot.create(:application))
|
|
336
374
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
337
375
|
expect(last_token).to be_nil
|
|
338
376
|
end
|
|
339
377
|
|
|
340
|
-
it
|
|
341
|
-
|
|
378
|
+
it "excludes tokens with a different resource owner" do
|
|
379
|
+
FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: 2)
|
|
342
380
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
343
381
|
expect(last_token).to be_nil
|
|
344
382
|
end
|
|
345
383
|
|
|
346
|
-
it
|
|
347
|
-
|
|
384
|
+
it "excludes tokens with fewer scopes" do
|
|
385
|
+
FactoryBot.create :access_token, default_attributes.merge(scopes: 'public')
|
|
348
386
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
349
387
|
expect(last_token).to be_nil
|
|
350
388
|
end
|
|
351
389
|
|
|
352
|
-
it '
|
|
353
|
-
|
|
390
|
+
it 'excludes tokens with different scopes' do
|
|
391
|
+
FactoryBot.create :access_token, default_attributes.merge(scopes: 'public email')
|
|
354
392
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
355
393
|
expect(last_token).to be_nil
|
|
356
394
|
end
|
|
357
395
|
|
|
358
|
-
it '
|
|
359
|
-
|
|
396
|
+
it 'excludes tokens with additional scopes' do
|
|
397
|
+
FactoryBot.create :access_token, default_attributes.merge(scopes: 'public write email')
|
|
360
398
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
361
399
|
expect(last_token).to be_nil
|
|
362
400
|
end
|
|
363
401
|
|
|
364
|
-
it '
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
application: application
|
|
402
|
+
it 'excludes tokens with scopes that are not present in server scopes' do
|
|
403
|
+
FactoryBot.create :access_token, default_attributes.merge(
|
|
404
|
+
application: application, scopes: 'public read'
|
|
368
405
|
)
|
|
369
406
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
370
407
|
expect(last_token).to be_nil
|
|
371
408
|
end
|
|
372
409
|
|
|
373
|
-
it '
|
|
374
|
-
|
|
375
|
-
|
|
410
|
+
it 'excludes tokens with scopes that are not present in application scopes' do
|
|
411
|
+
application = FactoryBot.create :application, scopes: "private read"
|
|
412
|
+
FactoryBot.create :access_token, default_attributes.merge(
|
|
413
|
+
application: application
|
|
414
|
+
)
|
|
376
415
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
416
|
+
expect(last_token).to be_nil
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
it 'does not match token if empty scope requested and token/app scopes present' do
|
|
420
|
+
application = FactoryBot.create :application, scopes: "sample:scope"
|
|
421
|
+
app_params = {
|
|
422
|
+
application_id: application.id, scopes: "sample:scope",
|
|
423
|
+
resource_owner_id: 100
|
|
424
|
+
}
|
|
425
|
+
FactoryBot.create :access_token, app_params
|
|
426
|
+
empty_scopes = Doorkeeper::OAuth::Scopes.from_string("")
|
|
427
|
+
last_token = AccessToken.matching_token_for(application, 100, empty_scopes)
|
|
428
|
+
expect(last_token).to be_nil
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
it 'matches token if empty scope requested and no token scopes present' do
|
|
432
|
+
empty_scopes = Doorkeeper::OAuth::Scopes.from_string("")
|
|
433
|
+
token = FactoryBot.create :access_token, default_attributes.merge(scopes: empty_scopes)
|
|
434
|
+
last_token = AccessToken.matching_token_for(application, 100, empty_scopes)
|
|
377
435
|
expect(last_token).to eq(token)
|
|
378
436
|
end
|
|
379
437
|
|
|
380
|
-
it 'returns
|
|
381
|
-
|
|
438
|
+
it 'returns the last matching token' do
|
|
439
|
+
FactoryBot.create :access_token, default_attributes.merge(created_at: 1.day.ago)
|
|
440
|
+
matching_token = FactoryBot.create :access_token, default_attributes
|
|
441
|
+
FactoryBot.create :access_token, default_attributes.merge(scopes: 'public')
|
|
442
|
+
|
|
443
|
+
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
444
|
+
expect(last_token).to eq(matching_token)
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
describe "#as_json" do
|
|
449
|
+
it "returns as_json hash" do
|
|
450
|
+
token = FactoryBot.create :access_token
|
|
382
451
|
token_hash = {
|
|
383
452
|
resource_owner_id: token.resource_owner_id,
|
|
384
|
-
|
|
385
|
-
|
|
453
|
+
scope: token.scopes,
|
|
454
|
+
expires_in: token.expires_in_seconds,
|
|
386
455
|
application: { uid: token.application.uid },
|
|
387
|
-
created_at: token.created_at.to_i
|
|
456
|
+
created_at: token.created_at.to_i
|
|
388
457
|
}
|
|
389
458
|
expect(token.as_json).to eq token_hash
|
|
390
459
|
end
|
|
391
460
|
end
|
|
392
|
-
|
|
393
461
|
end
|
|
394
462
|
end
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
module Doorkeeper
|
|
4
4
|
describe Application do
|
|
5
5
|
let(:require_owner) { Doorkeeper.configuration.instance_variable_set('@confirm_application_owner', true) }
|
|
6
6
|
let(:unset_require_owner) { Doorkeeper.configuration.instance_variable_set('@confirm_application_owner', false) }
|
|
7
|
-
let(:new_application) {
|
|
7
|
+
let(:new_application) { FactoryBot.build(:application) }
|
|
8
8
|
|
|
9
9
|
let(:uid) { SecureRandom.hex(8) }
|
|
10
10
|
let(:secret) { SecureRandom.hex(8) }
|
|
@@ -30,7 +30,7 @@ module Doorkeeper
|
|
|
30
30
|
context 'application owner is required' do
|
|
31
31
|
before(:each) do
|
|
32
32
|
require_owner
|
|
33
|
-
@owner =
|
|
33
|
+
@owner = FactoryBot.build_stubbed(:doorkeeper_testing_user)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
it 'is invalid without an owner' do
|
|
@@ -49,6 +49,11 @@ module Doorkeeper
|
|
|
49
49
|
expect(new_application).not_to be_valid
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
it 'is invalid without determining confidentiality' do
|
|
53
|
+
new_application.confidential = nil
|
|
54
|
+
expect(new_application).not_to be_valid
|
|
55
|
+
end
|
|
56
|
+
|
|
52
57
|
it 'generates uid on create' do
|
|
53
58
|
expect(new_application.uid).to be_nil
|
|
54
59
|
new_application.save
|
|
@@ -80,15 +85,15 @@ module Doorkeeper
|
|
|
80
85
|
end
|
|
81
86
|
|
|
82
87
|
it 'checks uniqueness of uid' do
|
|
83
|
-
app1 =
|
|
84
|
-
app2 =
|
|
88
|
+
app1 = FactoryBot.create(:application)
|
|
89
|
+
app2 = FactoryBot.create(:application)
|
|
85
90
|
app2.uid = app1.uid
|
|
86
91
|
expect(app2).not_to be_valid
|
|
87
92
|
end
|
|
88
93
|
|
|
89
94
|
it 'expects database to throw an error when uids are the same' do
|
|
90
|
-
app1 =
|
|
91
|
-
app2 =
|
|
95
|
+
app1 = FactoryBot.create(:application)
|
|
96
|
+
app2 = FactoryBot.create(:application)
|
|
92
97
|
app2.uid = app1.uid
|
|
93
98
|
expect { app2.save!(validate: false) }.to raise_error(uniqueness_error)
|
|
94
99
|
end
|
|
@@ -123,19 +128,52 @@ module Doorkeeper
|
|
|
123
128
|
end
|
|
124
129
|
|
|
125
130
|
it 'should destroy its access grants' do
|
|
126
|
-
|
|
131
|
+
FactoryBot.create(:access_grant, application: new_application)
|
|
127
132
|
expect { new_application.destroy }.to change { Doorkeeper::AccessGrant.count }.by(-1)
|
|
128
133
|
end
|
|
129
134
|
|
|
130
135
|
it 'should destroy its access tokens' do
|
|
131
|
-
|
|
132
|
-
|
|
136
|
+
FactoryBot.create(:access_token, application: new_application)
|
|
137
|
+
FactoryBot.create(:access_token, application: new_application, revoked_at: Time.now.utc)
|
|
133
138
|
expect do
|
|
134
139
|
new_application.destroy
|
|
135
140
|
end.to change { Doorkeeper::AccessToken.count }.by(-2)
|
|
136
141
|
end
|
|
137
142
|
end
|
|
138
143
|
|
|
144
|
+
describe :ordered_by do
|
|
145
|
+
let(:applications) { FactoryBot.create_list(:application, 5) }
|
|
146
|
+
|
|
147
|
+
context 'when a direction is not specified' do
|
|
148
|
+
it 'calls order with a default order of asc' do
|
|
149
|
+
names = applications.map(&:name).sort
|
|
150
|
+
expect(Application.ordered_by(:name).map(&:name)).to eq(names)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
context 'when a direction is specified' do
|
|
155
|
+
it 'calls order with specified direction' do
|
|
156
|
+
names = applications.map(&:name).sort.reverse
|
|
157
|
+
expect(Application.ordered_by(:name, :desc).map(&:name)).to eq(names)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
describe "#redirect_uri=" do
|
|
163
|
+
context "when array of valid redirect_uris" do
|
|
164
|
+
it "should join by newline" do
|
|
165
|
+
new_application.redirect_uri = ['http://localhost/callback1', 'http://localhost/callback2']
|
|
166
|
+
expect(new_application.redirect_uri).to eq("http://localhost/callback1\nhttp://localhost/callback2")
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
context "when string of valid redirect_uris" do
|
|
170
|
+
it "should store as-is" do
|
|
171
|
+
new_application.redirect_uri = "http://localhost/callback1\nhttp://localhost/callback2"
|
|
172
|
+
expect(new_application.redirect_uri).to eq("http://localhost/callback1\nhttp://localhost/callback2")
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
139
177
|
describe :authorized_for do
|
|
140
178
|
let(:resource_owner) { double(:resource_owner, id: 10) }
|
|
141
179
|
|
|
@@ -144,35 +182,88 @@ module Doorkeeper
|
|
|
144
182
|
end
|
|
145
183
|
|
|
146
184
|
it 'returns only application for a specific resource owner' do
|
|
147
|
-
|
|
148
|
-
token =
|
|
185
|
+
FactoryBot.create(:access_token, resource_owner_id: resource_owner.id + 1)
|
|
186
|
+
token = FactoryBot.create(:access_token, resource_owner_id: resource_owner.id)
|
|
149
187
|
expect(Application.authorized_for(resource_owner)).to eq([token.application])
|
|
150
188
|
end
|
|
151
189
|
|
|
152
190
|
it 'excludes revoked tokens' do
|
|
153
|
-
|
|
191
|
+
FactoryBot.create(:access_token, resource_owner_id: resource_owner.id, revoked_at: 2.days.ago)
|
|
154
192
|
expect(Application.authorized_for(resource_owner)).to be_empty
|
|
155
193
|
end
|
|
156
194
|
|
|
157
195
|
it 'returns all applications that have been authorized' do
|
|
158
|
-
token1 =
|
|
159
|
-
token2 =
|
|
196
|
+
token1 = FactoryBot.create(:access_token, resource_owner_id: resource_owner.id)
|
|
197
|
+
token2 = FactoryBot.create(:access_token, resource_owner_id: resource_owner.id)
|
|
160
198
|
expect(Application.authorized_for(resource_owner)).to eq([token1.application, token2.application])
|
|
161
199
|
end
|
|
162
200
|
|
|
163
201
|
it 'returns only one application even if it has been authorized twice' do
|
|
164
|
-
application =
|
|
165
|
-
|
|
166
|
-
|
|
202
|
+
application = FactoryBot.create(:application)
|
|
203
|
+
FactoryBot.create(:access_token, resource_owner_id: resource_owner.id, application: application)
|
|
204
|
+
FactoryBot.create(:access_token, resource_owner_id: resource_owner.id, application: application)
|
|
167
205
|
expect(Application.authorized_for(resource_owner)).to eq([application])
|
|
168
206
|
end
|
|
169
207
|
end
|
|
170
208
|
|
|
171
|
-
describe :
|
|
172
|
-
it '
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
expect(
|
|
209
|
+
describe :revoke_tokens_and_grants_for do
|
|
210
|
+
it 'revokes all access tokens and access grants' do
|
|
211
|
+
application_id = 42
|
|
212
|
+
resource_owner = double
|
|
213
|
+
expect(Doorkeeper::AccessToken).
|
|
214
|
+
to receive(:revoke_all_for).with(application_id, resource_owner)
|
|
215
|
+
expect(Doorkeeper::AccessGrant).
|
|
216
|
+
to receive(:revoke_all_for).with(application_id, resource_owner)
|
|
217
|
+
|
|
218
|
+
Application.revoke_tokens_and_grants_for(application_id, resource_owner)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
describe :by_uid_and_secret do
|
|
223
|
+
context "when application is private/confidential" do
|
|
224
|
+
it "finds the application via uid/secret" do
|
|
225
|
+
app = FactoryBot.create :application
|
|
226
|
+
authenticated = Application.by_uid_and_secret(app.uid, app.secret)
|
|
227
|
+
expect(authenticated).to eq(app)
|
|
228
|
+
end
|
|
229
|
+
context "when secret is wrong" do
|
|
230
|
+
it "should not find the application" do
|
|
231
|
+
app = FactoryBot.create :application
|
|
232
|
+
authenticated = Application.by_uid_and_secret(app.uid, 'bad')
|
|
233
|
+
expect(authenticated).to eq(nil)
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
context "when application is public/non-confidential" do
|
|
239
|
+
context "when secret is blank" do
|
|
240
|
+
it "should find the application" do
|
|
241
|
+
app = FactoryBot.create :application, confidential: false
|
|
242
|
+
authenticated = Application.by_uid_and_secret(app.uid, nil)
|
|
243
|
+
expect(authenticated).to eq(app)
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
context "when secret is wrong" do
|
|
247
|
+
it "should not find the application" do
|
|
248
|
+
app = FactoryBot.create :application, confidential: false
|
|
249
|
+
authenticated = Application.by_uid_and_secret(app.uid, 'bad')
|
|
250
|
+
expect(authenticated).to eq(nil)
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
describe :confidential? do
|
|
257
|
+
subject { FactoryBot.create(:application, confidential: confidential).confidential? }
|
|
258
|
+
|
|
259
|
+
context 'when application is private/confidential' do
|
|
260
|
+
let(:confidential) { true }
|
|
261
|
+
it { expect(subject).to eq(true) }
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
context 'when application is public/non-confidential' do
|
|
265
|
+
let(:confidential) { false }
|
|
266
|
+
it { expect(subject).to eq(false) }
|
|
176
267
|
end
|
|
177
268
|
end
|
|
178
269
|
end
|