doorkeeper 5.4.0.rc1 → 5.5.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 +108 -9
- data/README.md +4 -4
- data/app/controllers/doorkeeper/applications_controller.rb +3 -3
- data/app/controllers/doorkeeper/authorizations_controller.rb +16 -5
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
- data/app/controllers/doorkeeper/token_info_controller.rb +12 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +34 -26
- data/app/views/doorkeeper/applications/_form.html.erb +1 -1
- data/app/views/doorkeeper/applications/show.html.erb +16 -12
- data/app/views/doorkeeper/authorizations/form_post.html.erb +11 -0
- data/config/locales/en.yml +3 -1
- data/lib/doorkeeper.rb +6 -1
- data/lib/doorkeeper/config.rb +109 -78
- data/lib/doorkeeper/config/abstract_builder.rb +1 -1
- data/lib/doorkeeper/config/option.rb +1 -3
- data/lib/doorkeeper/config/validations.rb +53 -0
- data/lib/doorkeeper/engine.rb +1 -1
- data/lib/doorkeeper/grant_flow.rb +45 -0
- data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
- data/lib/doorkeeper/grant_flow/flow.rb +44 -0
- data/lib/doorkeeper/grant_flow/registry.rb +50 -0
- data/lib/doorkeeper/helpers/controller.rb +8 -4
- data/lib/doorkeeper/models/access_grant_mixin.rb +12 -7
- data/lib/doorkeeper/models/access_token_mixin.rb +12 -8
- data/lib/doorkeeper/models/application_mixin.rb +5 -4
- data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/code.rb +5 -1
- data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
- data/lib/doorkeeper/oauth/authorization/token.rb +11 -5
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +1 -1
- data/lib/doorkeeper/oauth/authorization_code_request.rb +10 -17
- data/lib/doorkeeper/oauth/base_request.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +3 -2
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +1 -0
- data/lib/doorkeeper/oauth/client_credentials/validator.rb +3 -1
- data/lib/doorkeeper/oauth/code_request.rb +2 -2
- data/lib/doorkeeper/oauth/code_response.rb +17 -11
- data/lib/doorkeeper/oauth/error_response.rb +4 -3
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -3
- data/lib/doorkeeper/oauth/password_access_token_request.rb +21 -2
- data/lib/doorkeeper/oauth/pre_authorization.rb +37 -11
- data/lib/doorkeeper/oauth/refresh_token_request.rb +13 -0
- data/lib/doorkeeper/oauth/token.rb +4 -5
- data/lib/doorkeeper/oauth/token_introspection.rb +1 -5
- data/lib/doorkeeper/oauth/token_request.rb +1 -1
- data/lib/doorkeeper/orm/active_record.rb +5 -6
- data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +12 -2
- data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +10 -2
- data/lib/doorkeeper/orm/active_record/mixins/application.rb +76 -10
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +5 -0
- data/lib/doorkeeper/rails/routes.rb +1 -3
- data/lib/doorkeeper/rake/db.rake +3 -3
- data/lib/doorkeeper/rake/setup.rake +5 -0
- data/lib/doorkeeper/request.rb +49 -12
- data/lib/doorkeeper/request/refresh_token.rb +2 -1
- data/lib/doorkeeper/server.rb +1 -1
- data/lib/doorkeeper/stale_records_cleaner.rb +4 -4
- data/lib/doorkeeper/version.rb +2 -6
- data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +1 -1
- data/lib/generators/doorkeeper/templates/initializer.rb +9 -7
- data/lib/generators/doorkeeper/templates/migration.rb.erb +12 -5
- metadata +25 -306
- data/Appraisals +0 -26
- data/CODE_OF_CONDUCT.md +0 -46
- data/CONTRIBUTING.md +0 -49
- data/Dangerfile +0 -67
- data/Dockerfile +0 -29
- data/Gemfile +0 -25
- data/NEWS.md +0 -1
- data/RELEASING.md +0 -11
- data/Rakefile +0 -28
- data/SECURITY.md +0 -15
- data/UPGRADE.md +0 -2
- data/bin/console +0 -30
- data/doorkeeper.gemspec +0 -42
- data/gemfiles/rails_5_0.gemfile +0 -19
- data/gemfiles/rails_5_1.gemfile +0 -19
- data/gemfiles/rails_5_2.gemfile +0 -19
- data/gemfiles/rails_6_0.gemfile +0 -19
- data/gemfiles/rails_master.gemfile +0 -19
- data/spec/controllers/application_metal_controller_spec.rb +0 -64
- data/spec/controllers/applications_controller_spec.rb +0 -274
- data/spec/controllers/authorizations_controller_spec.rb +0 -743
- data/spec/controllers/protected_resources_controller_spec.rb +0 -361
- data/spec/controllers/token_info_controller_spec.rb +0 -50
- data/spec/controllers/tokens_controller_spec.rb +0 -499
- data/spec/dummy/Rakefile +0 -9
- data/spec/dummy/app/assets/config/manifest.js +0 -2
- data/spec/dummy/app/controllers/application_controller.rb +0 -5
- data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
- data/spec/dummy/app/controllers/home_controller.rb +0 -18
- data/spec/dummy/app/controllers/metal_controller.rb +0 -13
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
- data/spec/dummy/app/helpers/application_helper.rb +0 -7
- data/spec/dummy/app/models/user.rb +0 -11
- data/spec/dummy/app/views/home/index.html.erb +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/dummy/config.ru +0 -6
- data/spec/dummy/config/application.rb +0 -51
- data/spec/dummy/config/boot.rb +0 -7
- data/spec/dummy/config/database.yml +0 -15
- data/spec/dummy/config/environment.rb +0 -5
- data/spec/dummy/config/environments/development.rb +0 -31
- data/spec/dummy/config/environments/production.rb +0 -64
- data/spec/dummy/config/environments/test.rb +0 -45
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
- data/spec/dummy/config/initializers/doorkeeper.rb +0 -166
- data/spec/dummy/config/initializers/secret_token.rb +0 -10
- data/spec/dummy/config/initializers/session_store.rb +0 -10
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
- data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
- data/spec/dummy/config/routes.rb +0 -13
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
- data/spec/dummy/db/schema.rb +0 -70
- data/spec/dummy/public/404.html +0 -26
- data/spec/dummy/public/422.html +0 -26
- data/spec/dummy/public/500.html +0 -26
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +0 -9
- data/spec/factories.rb +0 -30
- data/spec/generators/application_owner_generator_spec.rb +0 -28
- data/spec/generators/confidential_applications_generator_spec.rb +0 -29
- data/spec/generators/enable_polymorphic_resource_owner_generator_spec.rb +0 -47
- data/spec/generators/install_generator_spec.rb +0 -36
- data/spec/generators/migration_generator_spec.rb +0 -28
- data/spec/generators/pkce_generator_spec.rb +0 -28
- data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
- data/spec/generators/templates/routes.rb +0 -4
- data/spec/generators/views_generator_spec.rb +0 -29
- data/spec/grape/grape_integration_spec.rb +0 -137
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
- data/spec/lib/config_spec.rb +0 -813
- data/spec/lib/doorkeeper_spec.rb +0 -27
- data/spec/lib/models/expirable_spec.rb +0 -61
- data/spec/lib/models/reusable_spec.rb +0 -40
- data/spec/lib/models/revocable_spec.rb +0 -58
- data/spec/lib/models/scopes_spec.rb +0 -61
- data/spec/lib/models/secret_storable_spec.rb +0 -135
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
- data/spec/lib/oauth/authorization_code_request_spec.rb +0 -180
- data/spec/lib/oauth/base_request_spec.rb +0 -210
- data/spec/lib/oauth/base_response_spec.rb +0 -45
- data/spec/lib/oauth/client/credentials_spec.rb +0 -90
- data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -135
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -110
- data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -57
- data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
- data/spec/lib/oauth/client_credentials_request_spec.rb +0 -108
- data/spec/lib/oauth/client_spec.rb +0 -38
- data/spec/lib/oauth/code_request_spec.rb +0 -46
- data/spec/lib/oauth/code_response_spec.rb +0 -36
- data/spec/lib/oauth/error_response_spec.rb +0 -64
- data/spec/lib/oauth/error_spec.rb +0 -21
- data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -20
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -110
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -262
- data/spec/lib/oauth/invalid_request_response_spec.rb +0 -73
- data/spec/lib/oauth/invalid_token_response_spec.rb +0 -53
- data/spec/lib/oauth/password_access_token_request_spec.rb +0 -201
- data/spec/lib/oauth/pre_authorization_spec.rb +0 -218
- data/spec/lib/oauth/refresh_token_request_spec.rb +0 -166
- data/spec/lib/oauth/scopes_spec.rb +0 -146
- data/spec/lib/oauth/token_request_spec.rb +0 -164
- data/spec/lib/oauth/token_response_spec.rb +0 -84
- data/spec/lib/oauth/token_spec.rb +0 -156
- data/spec/lib/option_spec.rb +0 -51
- data/spec/lib/request/strategy_spec.rb +0 -54
- data/spec/lib/secret_storing/base_spec.rb +0 -60
- data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
- data/spec/lib/secret_storing/plain_spec.rb +0 -44
- data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
- data/spec/lib/server_spec.rb +0 -49
- data/spec/lib/stale_records_cleaner_spec.rb +0 -102
- data/spec/models/doorkeeper/access_grant_spec.rb +0 -175
- data/spec/models/doorkeeper/access_token_spec.rb +0 -650
- data/spec/models/doorkeeper/application_spec.rb +0 -442
- data/spec/requests/applications/applications_request_spec.rb +0 -259
- data/spec/requests/applications/authorized_applications_spec.rb +0 -32
- data/spec/requests/endpoints/authorization_spec.rb +0 -91
- data/spec/requests/endpoints/token_spec.rb +0 -79
- data/spec/requests/flows/authorization_code_errors_spec.rb +0 -82
- data/spec/requests/flows/authorization_code_spec.rb +0 -530
- data/spec/requests/flows/client_credentials_spec.rb +0 -207
- data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -46
- data/spec/requests/flows/implicit_grant_spec.rb +0 -91
- data/spec/requests/flows/password_spec.rb +0 -316
- data/spec/requests/flows/refresh_token_spec.rb +0 -241
- data/spec/requests/flows/revoke_token_spec.rb +0 -196
- data/spec/requests/flows/skip_authorization_spec.rb +0 -66
- data/spec/requests/protected_resources/metal_spec.rb +0 -16
- data/spec/requests/protected_resources/private_api_spec.rb +0 -83
- data/spec/routing/custom_controller_routes_spec.rb +0 -133
- data/spec/routing/default_routes_spec.rb +0 -41
- data/spec/routing/scoped_routes_spec.rb +0 -47
- data/spec/spec_helper.rb +0 -54
- data/spec/spec_helper_integration.rb +0 -4
- data/spec/support/dependencies/factory_bot.rb +0 -4
- data/spec/support/doorkeeper_rspec.rb +0 -22
- data/spec/support/helpers/access_token_request_helper.rb +0 -14
- data/spec/support/helpers/authorization_request_helper.rb +0 -43
- data/spec/support/helpers/config_helper.rb +0 -11
- data/spec/support/helpers/model_helper.rb +0 -78
- data/spec/support/helpers/request_spec_helper.rb +0 -110
- data/spec/support/helpers/url_helper.rb +0 -62
- data/spec/support/orm/active_record.rb +0 -5
- data/spec/support/shared/controllers_shared_context.rb +0 -133
- data/spec/support/shared/hashing_shared_context.rb +0 -36
- data/spec/support/shared/models_shared_examples.rb +0 -56
- data/spec/validators/redirect_uri_validator_spec.rb +0 -183
- data/spec/version/version_spec.rb +0 -17
@@ -1,442 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "spec_helper"
|
4
|
-
require "bcrypt"
|
5
|
-
|
6
|
-
describe Doorkeeper::Application do
|
7
|
-
let(:require_owner) { Doorkeeper.config.instance_variable_set("@confirm_application_owner", true) }
|
8
|
-
let(:unset_require_owner) { Doorkeeper.config.instance_variable_set("@confirm_application_owner", false) }
|
9
|
-
let(:new_application) { FactoryBot.build(:application) }
|
10
|
-
|
11
|
-
let(:uid) { SecureRandom.hex(8) }
|
12
|
-
let(:secret) { SecureRandom.hex(8) }
|
13
|
-
|
14
|
-
it "is invalid without a name" do
|
15
|
-
new_application.name = nil
|
16
|
-
expect(new_application).not_to be_valid
|
17
|
-
end
|
18
|
-
|
19
|
-
it "is invalid without determining confidentiality" do
|
20
|
-
new_application.confidential = nil
|
21
|
-
expect(new_application).not_to be_valid
|
22
|
-
end
|
23
|
-
|
24
|
-
it "generates uid on create" do
|
25
|
-
expect(new_application.uid).to be_nil
|
26
|
-
new_application.save
|
27
|
-
expect(new_application.uid).not_to be_nil
|
28
|
-
end
|
29
|
-
|
30
|
-
it "generates uid on create if an empty string" do
|
31
|
-
new_application.uid = ""
|
32
|
-
new_application.save
|
33
|
-
expect(new_application.uid).not_to be_blank
|
34
|
-
end
|
35
|
-
|
36
|
-
it "generates uid on create unless one is set" do
|
37
|
-
new_application.uid = uid
|
38
|
-
new_application.save
|
39
|
-
expect(new_application.uid).to eq(uid)
|
40
|
-
end
|
41
|
-
|
42
|
-
it "is invalid without uid" do
|
43
|
-
new_application.save
|
44
|
-
new_application.uid = nil
|
45
|
-
expect(new_application).not_to be_valid
|
46
|
-
end
|
47
|
-
|
48
|
-
it "checks uniqueness of uid" do
|
49
|
-
app1 = FactoryBot.create(:application)
|
50
|
-
app2 = FactoryBot.create(:application)
|
51
|
-
app2.uid = app1.uid
|
52
|
-
expect(app2).not_to be_valid
|
53
|
-
end
|
54
|
-
|
55
|
-
it "expects database to throw an error when uids are the same" do
|
56
|
-
app1 = FactoryBot.create(:application)
|
57
|
-
app2 = FactoryBot.create(:application)
|
58
|
-
app2.uid = app1.uid
|
59
|
-
expect { app2.save!(validate: false) }.to raise_error(uniqueness_error)
|
60
|
-
end
|
61
|
-
|
62
|
-
it "generate secret on create" do
|
63
|
-
expect(new_application.secret).to be_nil
|
64
|
-
new_application.save
|
65
|
-
expect(new_application.secret).not_to be_nil
|
66
|
-
end
|
67
|
-
|
68
|
-
it "generate secret on create if is blank string" do
|
69
|
-
new_application.secret = ""
|
70
|
-
new_application.save
|
71
|
-
expect(new_application.secret).not_to be_blank
|
72
|
-
end
|
73
|
-
|
74
|
-
it "generate secret on create unless one is set" do
|
75
|
-
new_application.secret = secret
|
76
|
-
new_application.save
|
77
|
-
expect(new_application.secret).to eq(secret)
|
78
|
-
end
|
79
|
-
|
80
|
-
it "is invalid without secret" do
|
81
|
-
new_application.save
|
82
|
-
new_application.secret = nil
|
83
|
-
expect(new_application).not_to be_valid
|
84
|
-
end
|
85
|
-
|
86
|
-
context "application_owner is enabled" do
|
87
|
-
before do
|
88
|
-
Doorkeeper.configure do
|
89
|
-
orm DOORKEEPER_ORM
|
90
|
-
enable_application_owner
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
context "application owner is not required" do
|
95
|
-
before(:each) do
|
96
|
-
unset_require_owner
|
97
|
-
end
|
98
|
-
|
99
|
-
it "is valid given valid attributes" do
|
100
|
-
expect(new_application).to be_valid
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
context "application owner is required" do
|
105
|
-
before(:each) do
|
106
|
-
require_owner
|
107
|
-
@owner = FactoryBot.build_stubbed(:doorkeeper_testing_user)
|
108
|
-
end
|
109
|
-
|
110
|
-
it "is invalid without an owner" do
|
111
|
-
expect(new_application).not_to be_valid
|
112
|
-
end
|
113
|
-
|
114
|
-
it "is valid with an owner" do
|
115
|
-
new_application.owner = @owner
|
116
|
-
expect(new_application).to be_valid
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
context "redirect URI" do
|
122
|
-
context "when grant flows allow blank redirect URI" do
|
123
|
-
before do
|
124
|
-
Doorkeeper.configure do
|
125
|
-
grant_flows %w[password client_credentials]
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
it "is valid without redirect_uri" do
|
130
|
-
new_application.save
|
131
|
-
new_application.redirect_uri = nil
|
132
|
-
expect(new_application).to be_valid
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
context "when grant flows require redirect URI" do
|
137
|
-
before do
|
138
|
-
Doorkeeper.configure do
|
139
|
-
grant_flows %w[password client_credentials authorization_code]
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
it "is invalid without redirect_uri" do
|
144
|
-
new_application.save
|
145
|
-
new_application.redirect_uri = nil
|
146
|
-
expect(new_application).not_to be_valid
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
context "when blank URI option disabled" do
|
151
|
-
before do
|
152
|
-
Doorkeeper.configure do
|
153
|
-
grant_flows %w[password client_credentials]
|
154
|
-
allow_blank_redirect_uri false
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
it "is invalid without redirect_uri" do
|
159
|
-
new_application.save
|
160
|
-
new_application.redirect_uri = nil
|
161
|
-
expect(new_application).not_to be_valid
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
context "with hashing enabled" do
|
167
|
-
include_context "with application hashing enabled"
|
168
|
-
let(:app) { FactoryBot.create :application }
|
169
|
-
let(:default_strategy) { Doorkeeper::SecretStoring::Sha256Hash }
|
170
|
-
|
171
|
-
it "uses SHA256 to avoid additional dependencies" do
|
172
|
-
# Ensure token was generated
|
173
|
-
app.validate
|
174
|
-
expect(app.secret).to eq(default_strategy.transform_secret(app.plaintext_secret))
|
175
|
-
end
|
176
|
-
|
177
|
-
context "when bcrypt strategy is configured" do
|
178
|
-
# In this text context, we have bcrypt loaded so `bcrypt_present?`
|
179
|
-
# will always be true
|
180
|
-
before do
|
181
|
-
Doorkeeper.configure do
|
182
|
-
hash_application_secrets using: "Doorkeeper::SecretStoring::BCrypt"
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
it "holds a volatile plaintext and BCrypt secret" do
|
187
|
-
expect(app.secret_strategy).to eq Doorkeeper::SecretStoring::BCrypt
|
188
|
-
expect(app.plaintext_secret).to be_a(String)
|
189
|
-
expect(app.secret).not_to eq(app.plaintext_secret)
|
190
|
-
expect { ::BCrypt::Password.create(app.secret) }.not_to raise_error
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
it "does not fallback to plain lookup by default" do
|
195
|
-
lookup = described_class.by_uid_and_secret(app.uid, app.secret)
|
196
|
-
expect(lookup).to eq(nil)
|
197
|
-
|
198
|
-
lookup = described_class.by_uid_and_secret(app.uid, app.plaintext_secret)
|
199
|
-
expect(lookup).to eq(app)
|
200
|
-
end
|
201
|
-
|
202
|
-
context "with fallback enabled" do
|
203
|
-
include_context "with token hashing and fallback lookup enabled"
|
204
|
-
|
205
|
-
it "provides plain and hashed lookup" do
|
206
|
-
lookup = described_class.by_uid_and_secret(app.uid, app.secret)
|
207
|
-
expect(lookup).to eq(app)
|
208
|
-
|
209
|
-
lookup = described_class.by_uid_and_secret(app.uid, app.plaintext_secret)
|
210
|
-
expect(lookup).to eq(app)
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
it "does not provide access to secret after loading" do
|
215
|
-
lookup = described_class.by_uid_and_secret(app.uid, app.plaintext_secret)
|
216
|
-
expect(lookup.plaintext_secret).to be_nil
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
describe "destroy related models on cascade" do
|
221
|
-
before(:each) do
|
222
|
-
new_application.save
|
223
|
-
end
|
224
|
-
|
225
|
-
let(:resource_owner) { FactoryBot.create(:resource_owner) }
|
226
|
-
|
227
|
-
it "should destroy its access grants" do
|
228
|
-
FactoryBot.create(
|
229
|
-
:access_grant,
|
230
|
-
application: new_application,
|
231
|
-
resource_owner_id: resource_owner.id,
|
232
|
-
resource_owner_type: resource_owner.class.name,
|
233
|
-
)
|
234
|
-
|
235
|
-
expect { new_application.destroy }.to change { Doorkeeper::AccessGrant.count }.by(-1)
|
236
|
-
end
|
237
|
-
|
238
|
-
it "should destroy its access tokens" do
|
239
|
-
FactoryBot.create(:access_token, application: new_application)
|
240
|
-
FactoryBot.create(:access_token, application: new_application, revoked_at: Time.now.utc)
|
241
|
-
expect do
|
242
|
-
new_application.destroy
|
243
|
-
end.to change { Doorkeeper::AccessToken.count }.by(-2)
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
describe "#ordered_by" do
|
248
|
-
let(:applications) { FactoryBot.create_list(:application, 5) }
|
249
|
-
|
250
|
-
context "when a direction is not specified" do
|
251
|
-
it "calls order with a default order of asc" do
|
252
|
-
names = applications.map(&:name).sort
|
253
|
-
expect(described_class.ordered_by(:name).map(&:name)).to eq(names)
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
context "when a direction is specified" do
|
258
|
-
it "calls order with specified direction" do
|
259
|
-
names = applications.map(&:name).sort.reverse
|
260
|
-
expect(described_class.ordered_by(:name, :desc).map(&:name)).to eq(names)
|
261
|
-
end
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
describe "#redirect_uri=" do
|
266
|
-
context "when array of valid redirect_uris" do
|
267
|
-
it "should join by newline" do
|
268
|
-
new_application.redirect_uri = ["http://localhost/callback1", "http://localhost/callback2"]
|
269
|
-
expect(new_application.redirect_uri).to eq("http://localhost/callback1\nhttp://localhost/callback2")
|
270
|
-
end
|
271
|
-
end
|
272
|
-
context "when string of valid redirect_uris" do
|
273
|
-
it "should store as-is" do
|
274
|
-
new_application.redirect_uri = "http://localhost/callback1\nhttp://localhost/callback2"
|
275
|
-
expect(new_application.redirect_uri).to eq("http://localhost/callback1\nhttp://localhost/callback2")
|
276
|
-
end
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
describe "#renew_secret" do
|
281
|
-
let(:app) { FactoryBot.create :application }
|
282
|
-
|
283
|
-
it "should generate a new secret" do
|
284
|
-
old_secret = app.secret
|
285
|
-
app.renew_secret
|
286
|
-
expect(old_secret).not_to eq(app.secret)
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
describe "#authorized_for" do
|
291
|
-
let(:resource_owner) { FactoryBot.create(:resource_owner) }
|
292
|
-
let(:other_resource_owner) { FactoryBot.create(:resource_owner) }
|
293
|
-
|
294
|
-
it "is empty if the application is not authorized for anyone" do
|
295
|
-
expect(described_class.authorized_for(resource_owner)).to be_empty
|
296
|
-
end
|
297
|
-
|
298
|
-
it "returns only application for a specific resource owner" do
|
299
|
-
FactoryBot.create(
|
300
|
-
:access_token,
|
301
|
-
resource_owner_id: other_resource_owner.id,
|
302
|
-
resource_owner_type: other_resource_owner.class.name,
|
303
|
-
)
|
304
|
-
token = FactoryBot.create(
|
305
|
-
:access_token,
|
306
|
-
resource_owner_id: resource_owner.id,
|
307
|
-
resource_owner_type: resource_owner.class.name,
|
308
|
-
)
|
309
|
-
expect(described_class.authorized_for(resource_owner)).to eq([token.application])
|
310
|
-
end
|
311
|
-
|
312
|
-
it "excludes revoked tokens" do
|
313
|
-
FactoryBot.create(
|
314
|
-
:access_token,
|
315
|
-
resource_owner_id: resource_owner.id,
|
316
|
-
resource_owner_type: resource_owner.class.name,
|
317
|
-
revoked_at: 2.days.ago,
|
318
|
-
)
|
319
|
-
expect(described_class.authorized_for(resource_owner)).to be_empty
|
320
|
-
end
|
321
|
-
|
322
|
-
it "returns all applications that have been authorized" do
|
323
|
-
token1 = FactoryBot.create(
|
324
|
-
:access_token,
|
325
|
-
resource_owner_id: resource_owner.id,
|
326
|
-
resource_owner_type: resource_owner.class.name,
|
327
|
-
)
|
328
|
-
token2 = FactoryBot.create(
|
329
|
-
:access_token,
|
330
|
-
resource_owner_id: resource_owner.id,
|
331
|
-
resource_owner_type: resource_owner.class.name,
|
332
|
-
)
|
333
|
-
expect(described_class.authorized_for(resource_owner))
|
334
|
-
.to eq([token1.application, token2.application])
|
335
|
-
end
|
336
|
-
|
337
|
-
it "returns only one application even if it has been authorized twice" do
|
338
|
-
application = FactoryBot.create(:application)
|
339
|
-
FactoryBot.create(
|
340
|
-
:access_token,
|
341
|
-
resource_owner_id: resource_owner.id,
|
342
|
-
resource_owner_type: resource_owner.class.name,
|
343
|
-
application: application,
|
344
|
-
)
|
345
|
-
FactoryBot.create(
|
346
|
-
:access_token,
|
347
|
-
resource_owner_id: resource_owner.id,
|
348
|
-
resource_owner_type: resource_owner.class.name,
|
349
|
-
application: application,
|
350
|
-
)
|
351
|
-
expect(described_class.authorized_for(resource_owner)).to eq([application])
|
352
|
-
end
|
353
|
-
end
|
354
|
-
|
355
|
-
describe "#revoke_tokens_and_grants_for" do
|
356
|
-
it "revokes all access tokens and access grants" do
|
357
|
-
application_id = 42
|
358
|
-
resource_owner = double
|
359
|
-
expect(Doorkeeper::AccessToken)
|
360
|
-
.to receive(:revoke_all_for).with(application_id, resource_owner)
|
361
|
-
expect(Doorkeeper::AccessGrant)
|
362
|
-
.to receive(:revoke_all_for).with(application_id, resource_owner)
|
363
|
-
|
364
|
-
described_class.revoke_tokens_and_grants_for(application_id, resource_owner)
|
365
|
-
end
|
366
|
-
end
|
367
|
-
|
368
|
-
describe "#by_uid_and_secret" do
|
369
|
-
context "when application is private/confidential" do
|
370
|
-
it "finds the application via uid/secret" do
|
371
|
-
app = FactoryBot.create :application
|
372
|
-
authenticated = described_class.by_uid_and_secret(app.uid, app.secret)
|
373
|
-
expect(authenticated).to eq(app)
|
374
|
-
end
|
375
|
-
context "when secret is wrong" do
|
376
|
-
it "should not find the application" do
|
377
|
-
app = FactoryBot.create :application
|
378
|
-
authenticated = described_class.by_uid_and_secret(app.uid, "bad")
|
379
|
-
expect(authenticated).to eq(nil)
|
380
|
-
end
|
381
|
-
end
|
382
|
-
end
|
383
|
-
|
384
|
-
context "when application is public/non-confidential" do
|
385
|
-
context "when secret is blank" do
|
386
|
-
it "should find the application" do
|
387
|
-
app = FactoryBot.create :application, confidential: false
|
388
|
-
authenticated = described_class.by_uid_and_secret(app.uid, nil)
|
389
|
-
expect(authenticated).to eq(app)
|
390
|
-
end
|
391
|
-
end
|
392
|
-
context "when secret is wrong" do
|
393
|
-
it "should not find the application" do
|
394
|
-
app = FactoryBot.create :application, confidential: false
|
395
|
-
authenticated = described_class.by_uid_and_secret(app.uid, "bad")
|
396
|
-
expect(authenticated).to eq(nil)
|
397
|
-
end
|
398
|
-
end
|
399
|
-
end
|
400
|
-
end
|
401
|
-
|
402
|
-
describe "#confidential?" do
|
403
|
-
subject { FactoryBot.create(:application, confidential: confidential).confidential? }
|
404
|
-
|
405
|
-
context "when application is private/confidential" do
|
406
|
-
let(:confidential) { true }
|
407
|
-
it { expect(subject).to eq(true) }
|
408
|
-
end
|
409
|
-
|
410
|
-
context "when application is public/non-confidential" do
|
411
|
-
let(:confidential) { false }
|
412
|
-
it { expect(subject).to eq(false) }
|
413
|
-
end
|
414
|
-
end
|
415
|
-
|
416
|
-
describe "#as_json" do
|
417
|
-
let(:app) { FactoryBot.create :application, secret: "123123123" }
|
418
|
-
|
419
|
-
before do
|
420
|
-
allow(Doorkeeper.configuration)
|
421
|
-
.to receive(:application_secret_strategy).and_return(Doorkeeper::SecretStoring::Plain)
|
422
|
-
end
|
423
|
-
|
424
|
-
it "includes plaintext secret" do
|
425
|
-
expect(app.as_json).to include("secret" => "123123123")
|
426
|
-
end
|
427
|
-
|
428
|
-
it "respects custom options" do
|
429
|
-
expect(app.as_json(except: :secret)).not_to include("secret")
|
430
|
-
expect(app.as_json(only: :id)).to match("id" => app.id)
|
431
|
-
end
|
432
|
-
|
433
|
-
# AR specific
|
434
|
-
if DOORKEEPER_ORM == :active_record
|
435
|
-
it "correctly works with #to_json" do
|
436
|
-
ActiveRecord::Base.include_root_in_json = true
|
437
|
-
expect(app.to_json(include_root_in_json: true)).to match(/application.+?:\{/)
|
438
|
-
ActiveRecord::Base.include_root_in_json = false
|
439
|
-
end
|
440
|
-
end
|
441
|
-
end
|
442
|
-
end
|
@@ -1,259 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
|
-
feature "Adding applications" do
|
6
|
-
context "in application form" do
|
7
|
-
background do
|
8
|
-
i_am_logged_in
|
9
|
-
visit "/oauth/applications/new"
|
10
|
-
end
|
11
|
-
|
12
|
-
scenario "adding a valid app" do
|
13
|
-
fill_in "doorkeeper_application[name]", with: "My Application"
|
14
|
-
fill_in "doorkeeper_application[redirect_uri]",
|
15
|
-
with: "https://example.com"
|
16
|
-
|
17
|
-
click_button "Submit"
|
18
|
-
i_should_see "Application created"
|
19
|
-
i_should_see "My Application"
|
20
|
-
end
|
21
|
-
|
22
|
-
scenario "adding invalid app" do
|
23
|
-
click_button "Submit"
|
24
|
-
i_should_see "Whoops! Check your form for possible errors"
|
25
|
-
end
|
26
|
-
|
27
|
-
scenario "adding app ignoring bad scope" do
|
28
|
-
config_is_set("enforce_configured_scopes", false)
|
29
|
-
|
30
|
-
fill_in "doorkeeper_application[name]", with: "My Application"
|
31
|
-
fill_in "doorkeeper_application[redirect_uri]",
|
32
|
-
with: "https://example.com"
|
33
|
-
fill_in "doorkeeper_application[scopes]", with: "blahblah"
|
34
|
-
|
35
|
-
click_button "Submit"
|
36
|
-
i_should_see "Application created"
|
37
|
-
i_should_see "My Application"
|
38
|
-
end
|
39
|
-
|
40
|
-
scenario "adding app validating bad scope" do
|
41
|
-
config_is_set("enforce_configured_scopes", true)
|
42
|
-
|
43
|
-
fill_in "doorkeeper_application[name]", with: "My Application"
|
44
|
-
fill_in "doorkeeper_application[redirect_uri]",
|
45
|
-
with: "https://example.com"
|
46
|
-
fill_in "doorkeeper_application[scopes]", with: "blahblah"
|
47
|
-
|
48
|
-
click_button "Submit"
|
49
|
-
i_should_see "Whoops! Check your form for possible errors"
|
50
|
-
end
|
51
|
-
|
52
|
-
scenario "adding app validating scope, blank scope is accepted" do
|
53
|
-
config_is_set("enforce_configured_scopes", true)
|
54
|
-
|
55
|
-
fill_in "doorkeeper_application[name]", with: "My Application"
|
56
|
-
fill_in "doorkeeper_application[redirect_uri]",
|
57
|
-
with: "https://example.com"
|
58
|
-
fill_in "doorkeeper_application[scopes]", with: ""
|
59
|
-
|
60
|
-
click_button "Submit"
|
61
|
-
i_should_see "Application created"
|
62
|
-
i_should_see "My Application"
|
63
|
-
end
|
64
|
-
|
65
|
-
scenario "adding app validating scope, multiple scopes configured" do
|
66
|
-
config_is_set("enforce_configured_scopes", true)
|
67
|
-
scopes = Doorkeeper::OAuth::Scopes.from_array(%w[read write admin])
|
68
|
-
config_is_set("optional_scopes", scopes)
|
69
|
-
|
70
|
-
fill_in "doorkeeper_application[name]", with: "My Application"
|
71
|
-
fill_in "doorkeeper_application[redirect_uri]",
|
72
|
-
with: "https://example.com"
|
73
|
-
fill_in "doorkeeper_application[scopes]", with: "read write"
|
74
|
-
|
75
|
-
click_button "Submit"
|
76
|
-
i_should_see "Application created"
|
77
|
-
i_should_see "My Application"
|
78
|
-
end
|
79
|
-
|
80
|
-
scenario "adding app validating scope, bad scope with multiple scopes configured" do
|
81
|
-
config_is_set("enforce_configured_scopes", true)
|
82
|
-
scopes = Doorkeeper::OAuth::Scopes.from_array(%w[read write admin])
|
83
|
-
config_is_set("optional_scopes", scopes)
|
84
|
-
|
85
|
-
fill_in "doorkeeper_application[name]", with: "My Application"
|
86
|
-
fill_in "doorkeeper_application[redirect_uri]",
|
87
|
-
with: "https://example.com"
|
88
|
-
fill_in "doorkeeper_application[scopes]", with: "read blah"
|
89
|
-
|
90
|
-
click_button "Submit"
|
91
|
-
i_should_see "Whoops! Check your form for possible errors"
|
92
|
-
i_should_see Regexp.new(
|
93
|
-
I18n.t("activerecord.errors.models.doorkeeper/application.attributes.scopes.not_match_configured"),
|
94
|
-
true,
|
95
|
-
)
|
96
|
-
end
|
97
|
-
|
98
|
-
context "redirect URI" do
|
99
|
-
scenario "adding app with blank redirect URI when configured flows requires redirect uri" do
|
100
|
-
config_is_set("grant_flows", %w[authorization_code implicit client_credentials])
|
101
|
-
|
102
|
-
fill_in "doorkeeper_application[name]", with: "My Application"
|
103
|
-
fill_in "doorkeeper_application[redirect_uri]",
|
104
|
-
with: ""
|
105
|
-
|
106
|
-
click_button "Submit"
|
107
|
-
i_should_see "Whoops! Check your form for possible errors"
|
108
|
-
end
|
109
|
-
|
110
|
-
scenario "adding app with blank redirect URI when configured flows without redirect uri" do
|
111
|
-
config_is_set("grant_flows", %w[client_credentials password])
|
112
|
-
|
113
|
-
# Visit it once again to consider grant flows
|
114
|
-
visit "/oauth/applications/new"
|
115
|
-
|
116
|
-
i_should_see I18n.t("doorkeeper.applications.help.blank_redirect_uri")
|
117
|
-
|
118
|
-
fill_in "doorkeeper_application[name]", with: "My Application"
|
119
|
-
fill_in "doorkeeper_application[redirect_uri]",
|
120
|
-
with: ""
|
121
|
-
|
122
|
-
click_button "Submit"
|
123
|
-
i_should_see "Application created"
|
124
|
-
i_should_see "My Application"
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
feature "Listing applications" do
|
131
|
-
background do
|
132
|
-
i_am_logged_in
|
133
|
-
|
134
|
-
FactoryBot.create :application, name: "Oauth Dude"
|
135
|
-
FactoryBot.create :application, name: "Awesome App"
|
136
|
-
end
|
137
|
-
|
138
|
-
scenario "application list" do
|
139
|
-
visit "/oauth/applications"
|
140
|
-
|
141
|
-
i_should_see "Awesome App"
|
142
|
-
i_should_see "Oauth Dude"
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
feature "Renders assets" do
|
147
|
-
scenario "admin stylesheets" do
|
148
|
-
visit "/assets/doorkeeper/admin/application.css"
|
149
|
-
|
150
|
-
i_should_see "Bootstrap"
|
151
|
-
i_should_see ".doorkeeper-admin"
|
152
|
-
end
|
153
|
-
|
154
|
-
scenario "application stylesheets" do
|
155
|
-
visit "/assets/doorkeeper/application.css"
|
156
|
-
|
157
|
-
i_should_see "Bootstrap"
|
158
|
-
i_should_see "#oauth-permissions"
|
159
|
-
i_should_see "#container"
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
feature "Show application" do
|
164
|
-
given :app do
|
165
|
-
i_am_logged_in
|
166
|
-
|
167
|
-
FactoryBot.create :application, name: "Just another oauth app"
|
168
|
-
end
|
169
|
-
|
170
|
-
scenario "visiting application page" do
|
171
|
-
visit "/oauth/applications/#{app.id}"
|
172
|
-
|
173
|
-
i_should_see "Just another oauth app"
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
feature "Edit application" do
|
178
|
-
let :app do
|
179
|
-
FactoryBot.create :application, name: "OMG my app"
|
180
|
-
end
|
181
|
-
|
182
|
-
background do
|
183
|
-
i_am_logged_in
|
184
|
-
|
185
|
-
visit "/oauth/applications/#{app.id}/edit"
|
186
|
-
end
|
187
|
-
|
188
|
-
scenario "updating a valid app" do
|
189
|
-
fill_in "doorkeeper_application[name]", with: "Serious app"
|
190
|
-
click_button "Submit"
|
191
|
-
|
192
|
-
i_should_see "Application updated"
|
193
|
-
i_should_see "Serious app"
|
194
|
-
i_should_not_see "OMG my app"
|
195
|
-
end
|
196
|
-
|
197
|
-
scenario "updating an invalid app" do
|
198
|
-
fill_in "doorkeeper_application[name]", with: ""
|
199
|
-
click_button "Submit"
|
200
|
-
|
201
|
-
i_should_see "Whoops! Check your form for possible errors"
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
feature "Remove application" do
|
206
|
-
background do
|
207
|
-
i_am_logged_in
|
208
|
-
|
209
|
-
@app = FactoryBot.create :application
|
210
|
-
end
|
211
|
-
|
212
|
-
scenario "deleting an application from list" do
|
213
|
-
visit "/oauth/applications"
|
214
|
-
|
215
|
-
i_should_see @app.name
|
216
|
-
|
217
|
-
within(:css, "tr#application_#{@app.id}") do
|
218
|
-
click_button "Destroy"
|
219
|
-
end
|
220
|
-
|
221
|
-
i_should_see "Application deleted"
|
222
|
-
i_should_not_see @app.name
|
223
|
-
end
|
224
|
-
|
225
|
-
scenario "deleting an application from show" do
|
226
|
-
visit "/oauth/applications/#{@app.id}"
|
227
|
-
click_button "Destroy"
|
228
|
-
|
229
|
-
i_should_see "Application deleted"
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
context "when admin authenticator block is default" do
|
234
|
-
let(:app) { FactoryBot.create :application, name: "app" }
|
235
|
-
|
236
|
-
feature "application list" do
|
237
|
-
scenario "fails with forbidden" do
|
238
|
-
visit "/oauth/applications"
|
239
|
-
|
240
|
-
should_have_status 403
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
feature "adding an app" do
|
245
|
-
scenario "fails with forbidden" do
|
246
|
-
visit "/oauth/applications/new"
|
247
|
-
|
248
|
-
should_have_status 403
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
feature "editing an app" do
|
253
|
-
scenario "fails with forbidden" do
|
254
|
-
visit "/oauth/applications/#{app.id}/edit"
|
255
|
-
|
256
|
-
should_have_status 403
|
257
|
-
end
|
258
|
-
end
|
259
|
-
end
|