doorkeeper 5.3.0 → 5.4.0.rc1
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/Appraisals +0 -14
- data/CHANGELOG.md +44 -1
- data/Dangerfile +7 -7
- data/Dockerfile +2 -2
- data/Gemfile +9 -9
- data/README.md +6 -4
- data/app/controllers/doorkeeper/applications_controller.rb +4 -4
- data/app/controllers/doorkeeper/authorizations_controller.rb +31 -12
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +57 -20
- data/app/views/doorkeeper/applications/show.html.erb +19 -2
- data/bin/console +14 -0
- data/config/locales/en.yml +3 -1
- data/doorkeeper.gemspec +1 -1
- data/gemfiles/rails_5_0.gemfile +8 -7
- data/gemfiles/rails_5_1.gemfile +8 -7
- data/gemfiles/rails_5_2.gemfile +8 -7
- data/gemfiles/rails_6_0.gemfile +8 -7
- data/gemfiles/rails_master.gemfile +8 -7
- data/lib/doorkeeper/config/abstract_builder.rb +28 -0
- data/lib/doorkeeper/config/option.rb +28 -14
- data/lib/doorkeeper/config.rb +41 -17
- data/lib/doorkeeper/grape/helpers.rb +1 -1
- data/lib/doorkeeper/models/access_grant_mixin.rb +9 -11
- data/lib/doorkeeper/models/access_token_mixin.rb +102 -42
- data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
- data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
- data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
- data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
- data/lib/doorkeeper/oauth/authorization/code.rb +14 -5
- data/lib/doorkeeper/oauth/authorization/context.rb +2 -2
- data/lib/doorkeeper/oauth/authorization/token.rb +7 -11
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
- data/lib/doorkeeper/oauth/authorization_code_request.rb +18 -8
- data/lib/doorkeeper/oauth/base_request.rb +11 -19
- data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
- data/lib/doorkeeper/oauth/client.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +25 -7
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
- data/lib/doorkeeper/oauth/client_credentials/validator.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
- data/lib/doorkeeper/oauth/code_request.rb +1 -1
- data/lib/doorkeeper/oauth/code_response.rb +6 -2
- data/lib/doorkeeper/oauth/error_response.rb +2 -4
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -5
- data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
- data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -2
- data/lib/doorkeeper/oauth/password_access_token_request.rb +3 -5
- data/lib/doorkeeper/oauth/pre_authorization.rb +32 -27
- data/lib/doorkeeper/oauth/refresh_token_request.rb +18 -22
- data/lib/doorkeeper/oauth/token.rb +1 -1
- data/lib/doorkeeper/oauth/token_introspection.rb +3 -3
- data/lib/doorkeeper/oauth/token_request.rb +2 -2
- data/lib/doorkeeper/oauth/token_response.rb +1 -1
- data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +7 -2
- data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +6 -2
- data/lib/doorkeeper/orm/active_record/mixins/application.rb +6 -2
- data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
- data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
- data/lib/doorkeeper/rails/routes/registry.rb +45 -0
- data/lib/doorkeeper/rails/routes.rb +13 -17
- data/lib/doorkeeper/request/strategy.rb +2 -2
- data/lib/doorkeeper/server.rb +3 -3
- data/lib/doorkeeper/version.rb +2 -2
- data/lib/doorkeeper.rb +106 -79
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
- data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
- data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +2 -0
- data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
- data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +47 -3
- data/lib/generators/doorkeeper/templates/migration.rb.erb +2 -0
- data/spec/controllers/applications_controller_spec.rb +2 -2
- data/spec/controllers/authorizations_controller_spec.rb +165 -30
- data/spec/controllers/tokens_controller_spec.rb +6 -5
- data/spec/dummy/app/helpers/application_helper.rb +1 -1
- data/spec/dummy/app/models/user.rb +5 -1
- data/spec/dummy/config/application.rb +6 -4
- data/spec/dummy/config/boot.rb +4 -4
- data/spec/dummy/config/environment.rb +1 -1
- data/spec/dummy/config/routes.rb +4 -4
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +2 -2
- data/spec/dummy/db/schema.rb +3 -1
- data/spec/factories.rb +1 -1
- data/spec/generators/enable_polymorphic_resource_owner_generator_spec.rb +47 -0
- data/spec/lib/config_spec.rb +30 -11
- data/spec/lib/models/revocable_spec.rb +2 -3
- data/spec/lib/models/scopes_spec.rb +8 -0
- data/spec/lib/oauth/authorization_code_request_spec.rb +25 -15
- data/spec/lib/oauth/base_request_spec.rb +6 -20
- data/spec/lib/oauth/client_credentials/creator_spec.rb +90 -89
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +84 -86
- data/spec/lib/oauth/client_credentials/validation_spec.rb +38 -40
- data/spec/lib/oauth/client_credentials_request_spec.rb +5 -4
- data/spec/lib/oauth/code_request_spec.rb +1 -1
- data/spec/lib/oauth/code_response_spec.rb +5 -1
- data/spec/lib/oauth/error_response_spec.rb +1 -1
- data/spec/lib/oauth/password_access_token_request_spec.rb +24 -13
- data/spec/lib/oauth/pre_authorization_spec.rb +13 -18
- data/spec/lib/oauth/refresh_token_request_spec.rb +19 -30
- data/spec/lib/oauth/token_request_spec.rb +14 -7
- data/spec/lib/option_spec.rb +51 -0
- data/spec/lib/stale_records_cleaner_spec.rb +18 -5
- data/spec/models/doorkeeper/access_grant_spec.rb +18 -4
- data/spec/models/doorkeeper/access_token_spec.rb +507 -479
- data/spec/models/doorkeeper/application_spec.rb +338 -300
- data/spec/requests/endpoints/token_spec.rb +5 -1
- data/spec/requests/flows/authorization_code_errors_spec.rb +4 -1
- data/spec/requests/flows/authorization_code_spec.rb +6 -1
- data/spec/requests/flows/client_credentials_spec.rb +41 -0
- data/spec/requests/flows/refresh_token_spec.rb +16 -8
- data/spec/requests/flows/revoke_token_spec.rb +143 -104
- data/spec/support/helpers/access_token_request_helper.rb +1 -0
- data/spec/support/helpers/authorization_request_helper.rb +4 -4
- data/spec/support/helpers/config_helper.rb +1 -1
- data/spec/support/shared/controllers_shared_context.rb +2 -2
- data/spec/support/shared/models_shared_examples.rb +6 -4
- metadata +15 -4
|
@@ -167,8 +167,8 @@ module Doorkeeper
|
|
|
167
167
|
|
|
168
168
|
# We don't know the application secret here (because its hashed) so we can not assert its text on the page
|
|
169
169
|
# Instead, we read it from the page and then check if it matches the application secret
|
|
170
|
-
code_element =
|
|
171
|
-
secret_from_page = code_element[1]
|
|
170
|
+
code_element = /code.*id="secret">\s*\K([^<]*)/m.match(response.body)
|
|
171
|
+
secret_from_page = code_element[1].strip
|
|
172
172
|
|
|
173
173
|
expect(response.body).to have_selector("code#application_id", text: application.uid)
|
|
174
174
|
expect(response.body).to have_selector("code#secret")
|
|
@@ -16,7 +16,14 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
|
|
|
16
16
|
|
|
17
17
|
let(:client) { FactoryBot.create :application }
|
|
18
18
|
let(:user) { User.create!(name: "Joe", password: "sekret") }
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
let(:access_token) do
|
|
21
|
+
FactoryBot.build :access_token,
|
|
22
|
+
resource_owner_id: user.id,
|
|
23
|
+
resource_owner_type: user.class.name,
|
|
24
|
+
application_id: client.id,
|
|
25
|
+
scopes: "default"
|
|
26
|
+
end
|
|
20
27
|
|
|
21
28
|
before do
|
|
22
29
|
Doorkeeper.configure do
|
|
@@ -136,6 +143,37 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
|
|
|
136
143
|
end
|
|
137
144
|
end
|
|
138
145
|
|
|
146
|
+
context "when user cannot access application" do
|
|
147
|
+
before do
|
|
148
|
+
allow(Doorkeeper.configuration).to receive(:authorize_resource_owner_for_client).and_return(->(*_) { false })
|
|
149
|
+
post :create, params: {
|
|
150
|
+
client_id: client.uid,
|
|
151
|
+
response_type: "token",
|
|
152
|
+
redirect_uri: client.redirect_uri,
|
|
153
|
+
}
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
let(:response_json_body) { JSON.parse(response.body) }
|
|
157
|
+
|
|
158
|
+
it "renders 400 error" do
|
|
159
|
+
expect(response.status).to eq 401
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it "includes error name" do
|
|
163
|
+
expect(response_json_body["error"]).to eq("invalid_client")
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it "includes error description" do
|
|
167
|
+
expect(response_json_body["error_description"]).to eq(
|
|
168
|
+
translated_error_message(:invalid_client),
|
|
169
|
+
)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
it "does not issue any access token" do
|
|
173
|
+
expect(Doorkeeper::AccessToken.all).to be_empty
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
139
177
|
context "when other error happens" do
|
|
140
178
|
before do
|
|
141
179
|
default_scopes_exist :public
|
|
@@ -207,6 +245,39 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
|
|
|
207
245
|
end
|
|
208
246
|
end
|
|
209
247
|
|
|
248
|
+
context "when user cannot access application" do
|
|
249
|
+
before do
|
|
250
|
+
allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
|
|
251
|
+
allow(Doorkeeper.configuration).to receive(:authorize_resource_owner_for_client).and_return(->(*_) { false })
|
|
252
|
+
|
|
253
|
+
post :create, params: {
|
|
254
|
+
client_id: client.uid,
|
|
255
|
+
response_type: "token",
|
|
256
|
+
redirect_uri: client.redirect_uri,
|
|
257
|
+
}
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
let(:response_json_body) { JSON.parse(response.body) }
|
|
261
|
+
|
|
262
|
+
it "renders 400 error" do
|
|
263
|
+
expect(response.status).to eq 401
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
it "includes error name" do
|
|
267
|
+
expect(response_json_body["error"]).to eq("invalid_client")
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
it "includes error description" do
|
|
271
|
+
expect(response_json_body["error_description"]).to eq(
|
|
272
|
+
translated_error_message(:invalid_client),
|
|
273
|
+
)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
it "does not issue any access token" do
|
|
277
|
+
expect(Doorkeeper::AccessToken.all).to be_empty
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
210
281
|
context "when other error happens" do
|
|
211
282
|
before do
|
|
212
283
|
allow(Doorkeeper.config).to receive(:api_only).and_return(true)
|
|
@@ -287,12 +358,14 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
|
|
|
287
358
|
|
|
288
359
|
it "should call :before_successful_authorization callback" do
|
|
289
360
|
expect(Doorkeeper.config)
|
|
290
|
-
.to receive_message_chain(:before_successful_authorization, :call)
|
|
361
|
+
.to receive_message_chain(:before_successful_authorization, :call)
|
|
362
|
+
.with(instance_of(described_class), instance_of(Doorkeeper::OAuth::Hooks::Context))
|
|
291
363
|
end
|
|
292
364
|
|
|
293
365
|
it "should call :after_successful_authorization callback" do
|
|
294
366
|
expect(Doorkeeper.config)
|
|
295
|
-
.to receive_message_chain(:after_successful_authorization, :call)
|
|
367
|
+
.to receive_message_chain(:after_successful_authorization, :call)
|
|
368
|
+
.with(instance_of(described_class), instance_of(Doorkeeper::OAuth::Hooks::Context))
|
|
296
369
|
end
|
|
297
370
|
end
|
|
298
371
|
|
|
@@ -482,46 +555,106 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
|
|
|
482
555
|
end
|
|
483
556
|
|
|
484
557
|
describe "GET #new with errors" do
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
558
|
+
context "without valid params" do
|
|
559
|
+
before do
|
|
560
|
+
default_scopes_exist :public
|
|
561
|
+
get :new, params: { an_invalid: "request" }
|
|
562
|
+
end
|
|
489
563
|
|
|
490
|
-
|
|
491
|
-
|
|
564
|
+
it "does not redirect" do
|
|
565
|
+
expect(response).to_not be_redirect
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
it "does not issue any token" do
|
|
569
|
+
expect(Doorkeeper::AccessGrant.count).to eq 0
|
|
570
|
+
expect(Doorkeeper::AccessToken.count).to eq 0
|
|
571
|
+
end
|
|
492
572
|
end
|
|
493
573
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
574
|
+
context "when user cannot access application" do
|
|
575
|
+
before do
|
|
576
|
+
allow(Doorkeeper.configuration).to receive(:authorize_resource_owner_for_client).and_return(->(*_) { false })
|
|
577
|
+
|
|
578
|
+
get :new, params: {
|
|
579
|
+
client_id: client.uid,
|
|
580
|
+
response_type: "token",
|
|
581
|
+
redirect_uri: client.redirect_uri,
|
|
582
|
+
}
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
it "does not redirect" do
|
|
586
|
+
expect(response).to_not be_redirect
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
it "does not issue any token" do
|
|
590
|
+
expect(Doorkeeper::AccessGrant.count).to eq 0
|
|
591
|
+
expect(Doorkeeper::AccessToken.count).to eq 0
|
|
592
|
+
end
|
|
497
593
|
end
|
|
498
594
|
end
|
|
499
595
|
|
|
500
596
|
describe "GET #new in API mode with errors" do
|
|
501
|
-
let(:response_json_body) { JSON.parse(response.body) }
|
|
502
|
-
|
|
503
597
|
before do
|
|
504
|
-
default_scopes_exist :public
|
|
505
598
|
allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
|
|
506
|
-
|
|
599
|
+
default_scopes_exist :public
|
|
507
600
|
end
|
|
508
601
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
602
|
+
context "without valid params" do
|
|
603
|
+
before do
|
|
604
|
+
get :new, params: { an_invalid: "request" }
|
|
605
|
+
end
|
|
512
606
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
607
|
+
let(:response_json_body) { JSON.parse(response.body) }
|
|
608
|
+
|
|
609
|
+
it "should render bad request" do
|
|
610
|
+
expect(response).to have_http_status(:bad_request)
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
it "includes error in body" do
|
|
614
|
+
expect(response_json_body["error"]).to eq("invalid_request")
|
|
615
|
+
end
|
|
516
616
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
617
|
+
it "includes error description in body" do
|
|
618
|
+
expect(response_json_body["error_description"])
|
|
619
|
+
.to eq(translated_invalid_request_error_message(:missing_param, :client_id))
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
it "does not issue any token" do
|
|
623
|
+
expect(Doorkeeper::AccessGrant.count).to eq 0
|
|
624
|
+
expect(Doorkeeper::AccessToken.count).to eq 0
|
|
625
|
+
end
|
|
520
626
|
end
|
|
521
627
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
628
|
+
context "when user cannot access application" do
|
|
629
|
+
before do
|
|
630
|
+
allow(Doorkeeper.configuration).to receive(:authorize_resource_owner_for_client).and_return(->(*_) { false })
|
|
631
|
+
|
|
632
|
+
get :new, params: {
|
|
633
|
+
client_id: client.uid,
|
|
634
|
+
response_type: "token",
|
|
635
|
+
redirect_uri: client.redirect_uri,
|
|
636
|
+
}
|
|
637
|
+
end
|
|
638
|
+
|
|
639
|
+
let(:response_json_body) { JSON.parse(response.body) }
|
|
640
|
+
|
|
641
|
+
it "should render bad request" do
|
|
642
|
+
expect(response).to have_http_status(:bad_request)
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
it "includes error in body" do
|
|
646
|
+
expect(response_json_body["error"]).to eq("invalid_client")
|
|
647
|
+
end
|
|
648
|
+
|
|
649
|
+
it "includes error description in body" do
|
|
650
|
+
expect(response_json_body["error_description"])
|
|
651
|
+
.to eq(translated_error_message(:invalid_client))
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
it "does not issue any token" do
|
|
655
|
+
expect(Doorkeeper::AccessGrant.count).to eq 0
|
|
656
|
+
expect(Doorkeeper::AccessToken.count).to eq 0
|
|
657
|
+
end
|
|
525
658
|
end
|
|
526
659
|
end
|
|
527
660
|
|
|
@@ -538,12 +671,14 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
|
|
|
538
671
|
|
|
539
672
|
it "should call :before_successful_authorization callback" do
|
|
540
673
|
expect(Doorkeeper.configuration)
|
|
541
|
-
.to receive_message_chain(:before_successful_authorization, :call)
|
|
674
|
+
.to receive_message_chain(:before_successful_authorization, :call)
|
|
675
|
+
.with(instance_of(described_class), instance_of(Doorkeeper::OAuth::Hooks::Context))
|
|
542
676
|
end
|
|
543
677
|
|
|
544
678
|
it "should call :after_successful_authorization callback" do
|
|
545
679
|
expect(Doorkeeper.configuration)
|
|
546
|
-
.to receive_message_chain(:after_successful_authorization, :call)
|
|
680
|
+
.to receive_message_chain(:after_successful_authorization, :call)
|
|
681
|
+
.with(instance_of(described_class), instance_of(Doorkeeper::OAuth::Hooks::Context))
|
|
547
682
|
end
|
|
548
683
|
end
|
|
549
684
|
|
|
@@ -106,12 +106,13 @@ describe Doorkeeper::TokensController do
|
|
|
106
106
|
|
|
107
107
|
it "should call :before_successful_authorization callback" do
|
|
108
108
|
expect(Doorkeeper.configuration)
|
|
109
|
-
.to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
|
|
109
|
+
.to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class), nil)
|
|
110
110
|
end
|
|
111
111
|
|
|
112
112
|
it "should call :after_successful_authorization callback" do
|
|
113
113
|
expect(Doorkeeper.configuration)
|
|
114
|
-
.to receive_message_chain(:after_successful_authorization, :call)
|
|
114
|
+
.to receive_message_chain(:after_successful_authorization, :call)
|
|
115
|
+
.with(instance_of(described_class), instance_of(Doorkeeper::OAuth::Hooks::Context))
|
|
115
116
|
end
|
|
116
117
|
end
|
|
117
118
|
|
|
@@ -126,7 +127,7 @@ describe Doorkeeper::TokensController do
|
|
|
126
127
|
|
|
127
128
|
it "should call :before_successful_authorization callback" do
|
|
128
129
|
expect(Doorkeeper.configuration)
|
|
129
|
-
.to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
|
|
130
|
+
.to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class), nil)
|
|
130
131
|
end
|
|
131
132
|
|
|
132
133
|
it "should not call :after_successful_authorization callback" do
|
|
@@ -174,13 +175,13 @@ describe Doorkeeper::TokensController do
|
|
|
174
175
|
let(:client) { FactoryBot.create(:application, confidential: false) }
|
|
175
176
|
|
|
176
177
|
it "returns 200" do
|
|
177
|
-
post :revoke, params: { token: access_token.token }
|
|
178
|
+
post :revoke, params: { client_id: client.uid, token: access_token.token }
|
|
178
179
|
|
|
179
180
|
expect(response.status).to eq 200
|
|
180
181
|
end
|
|
181
182
|
|
|
182
183
|
it "revokes the access token" do
|
|
183
|
-
post :revoke, params: { token: access_token.token }
|
|
184
|
+
post :revoke, params: { client_id: client.uid, token: access_token.token }
|
|
184
185
|
|
|
185
186
|
expect(access_token.reload).to have_attributes(revoked?: true)
|
|
186
187
|
end
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
class
|
|
3
|
+
class ApplicationRecord < ::ActiveRecord::Base
|
|
4
|
+
self.abstract_class = true
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class User < ApplicationRecord
|
|
4
8
|
def self.authenticate!(name, password)
|
|
5
9
|
User.where(name: name, password: password).first
|
|
6
10
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.expand_path(
|
|
1
|
+
require File.expand_path("boot", __dir__)
|
|
2
2
|
|
|
3
3
|
require "rails"
|
|
4
4
|
|
|
@@ -17,7 +17,7 @@ end
|
|
|
17
17
|
|
|
18
18
|
Bundler.require(*Rails.groups)
|
|
19
19
|
|
|
20
|
-
require
|
|
20
|
+
require "yaml"
|
|
21
21
|
|
|
22
22
|
orm = if DOORKEEPER_ORM =~ /mongoid/
|
|
23
23
|
Mongoid.load!(File.join(File.dirname(File.expand_path(__FILE__)), "#{DOORKEEPER_ORM}.yml"))
|
|
@@ -29,13 +29,15 @@ require "#{orm}/railtie"
|
|
|
29
29
|
|
|
30
30
|
module Dummy
|
|
31
31
|
class Application < Rails::Application
|
|
32
|
-
if Rails.gem_version < Gem::Version.new(
|
|
32
|
+
if Rails.gem_version < Gem::Version.new("5.1")
|
|
33
33
|
config.action_controller.per_form_csrf_tokens = true
|
|
34
34
|
config.action_controller.forgery_protection_origin_check = true
|
|
35
35
|
|
|
36
36
|
ActiveSupport.to_time_preserves_timezone = true
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
if DOORKEEPER_ORM =~ /active_record/
|
|
39
|
+
config.active_record.belongs_to_required_by_default = true
|
|
40
|
+
end
|
|
39
41
|
|
|
40
42
|
config.ssl_options = { hsts: { subdomains: true } }
|
|
41
43
|
else
|
data/spec/dummy/config/boot.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
1
|
+
require "rubygems"
|
|
2
|
+
require "bundler/setup"
|
|
3
3
|
|
|
4
|
-
orm = ENV[
|
|
4
|
+
orm = ENV["BUNDLE_GEMFILE"].match(/Gemfile\.(.+)\.rb/)
|
|
5
5
|
DOORKEEPER_ORM = (orm && orm[1]) || :active_record unless defined?(DOORKEEPER_ORM)
|
|
6
6
|
|
|
7
|
-
$LOAD_PATH.unshift File.expand_path(
|
|
7
|
+
$LOAD_PATH.unshift File.expand_path("../../../lib", __dir__)
|
data/spec/dummy/config/routes.rb
CHANGED
|
@@ -4,10 +4,10 @@ Rails.application.routes.draw do
|
|
|
4
4
|
resources :semi_protected_resources
|
|
5
5
|
resources :full_protected_resources
|
|
6
6
|
|
|
7
|
-
get
|
|
7
|
+
get "metal.json" => "metal#index"
|
|
8
8
|
|
|
9
|
-
get
|
|
10
|
-
get
|
|
9
|
+
get "/callback", to: "home#callback"
|
|
10
|
+
get "/sign_in", to: "home#sign_in"
|
|
11
11
|
|
|
12
|
-
root to:
|
|
12
|
+
root to: "home#index"
|
|
13
13
|
end
|
|
@@ -18,7 +18,7 @@ class CreateDoorkeeperTables < ActiveRecord::Migration[4.2]
|
|
|
18
18
|
add_index :oauth_applications, :uid, unique: true
|
|
19
19
|
|
|
20
20
|
create_table :oauth_access_grants do |t|
|
|
21
|
-
t.references :resource_owner, null: false
|
|
21
|
+
t.references :resource_owner, null: false, polymorphic: true
|
|
22
22
|
t.references :application, null: false
|
|
23
23
|
t.string :token, null: false
|
|
24
24
|
t.integer :expires_in, null: false
|
|
@@ -36,7 +36,7 @@ class CreateDoorkeeperTables < ActiveRecord::Migration[4.2]
|
|
|
36
36
|
)
|
|
37
37
|
|
|
38
38
|
create_table :oauth_access_tokens do |t|
|
|
39
|
-
t.references :resource_owner, index: true
|
|
39
|
+
t.references :resource_owner, index: true, polymorphic: true
|
|
40
40
|
t.references :application, null: false
|
|
41
41
|
|
|
42
42
|
# If you use a custom token generator you may need to change this column
|
data/spec/dummy/db/schema.rb
CHANGED
|
@@ -14,6 +14,7 @@ ActiveRecord::Schema.define(version: 20180210183654) do
|
|
|
14
14
|
|
|
15
15
|
create_table "oauth_access_grants", force: :cascade do |t|
|
|
16
16
|
t.integer "resource_owner_id", null: false
|
|
17
|
+
t.string "resource_owner_type" # [NOTE] null: false skipped to allow test pass
|
|
17
18
|
t.integer "application_id", null: false
|
|
18
19
|
t.string "token", null: false
|
|
19
20
|
t.integer "expires_in", null: false
|
|
@@ -21,7 +22,7 @@ ActiveRecord::Schema.define(version: 20180210183654) do
|
|
|
21
22
|
t.datetime "created_at", null: false
|
|
22
23
|
t.datetime "revoked_at"
|
|
23
24
|
t.string "scopes"
|
|
24
|
-
unless ENV[
|
|
25
|
+
unless ENV["WITHOUT_PKCE"]
|
|
25
26
|
t.string "code_challenge"
|
|
26
27
|
t.string "code_challenge_method"
|
|
27
28
|
end
|
|
@@ -30,6 +31,7 @@ ActiveRecord::Schema.define(version: 20180210183654) do
|
|
|
30
31
|
|
|
31
32
|
create_table "oauth_access_tokens", force: :cascade do |t|
|
|
32
33
|
t.integer "resource_owner_id"
|
|
34
|
+
t.string "resource_owner_type"
|
|
33
35
|
t.integer "application_id"
|
|
34
36
|
t.string "token", null: false
|
|
35
37
|
t.string "refresh_token"
|
data/spec/factories.rb
CHANGED
|
@@ -26,5 +26,5 @@ FactoryBot.define do
|
|
|
26
26
|
|
|
27
27
|
# do not name this factory :user, otherwise it will conflict with factories
|
|
28
28
|
# from applications that use doorkeeper factories in their own tests
|
|
29
|
-
factory :doorkeeper_testing_user, class: :user
|
|
29
|
+
factory :doorkeeper_testing_user, class: :user, aliases: [:resource_owner]
|
|
30
30
|
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
require "generators/doorkeeper/enable_polymorphic_resource_owner_generator"
|
|
5
|
+
|
|
6
|
+
describe "Doorkeeper::EnablePolymorphicResourceOwnerGenerator" do
|
|
7
|
+
include GeneratorSpec::TestCase
|
|
8
|
+
|
|
9
|
+
tests Doorkeeper::EnablePolymorphicResourceOwnerGenerator
|
|
10
|
+
destination ::File.expand_path("../tmp/dummy", __FILE__)
|
|
11
|
+
|
|
12
|
+
describe "after running the generator" do
|
|
13
|
+
before :each do
|
|
14
|
+
prepare_destination
|
|
15
|
+
FileUtils.mkdir_p(::File.expand_path("config/initializers", Pathname(destination_root)))
|
|
16
|
+
FileUtils.copy_file(
|
|
17
|
+
::File.expand_path("../../lib/generators/doorkeeper/templates/initializer.rb", __dir__),
|
|
18
|
+
::File.expand_path("config/initializers/doorkeeper.rb", Pathname.new(destination_root)),
|
|
19
|
+
)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "creates a migration with a version specifier and changes the initializer" do
|
|
23
|
+
stub_const("ActiveRecord::VERSION::MAJOR", 5)
|
|
24
|
+
stub_const("ActiveRecord::VERSION::MINOR", 0)
|
|
25
|
+
|
|
26
|
+
run_generator
|
|
27
|
+
|
|
28
|
+
assert_migration "db/migrate/enable_polymorphic_resource_owner.rb" do |migration|
|
|
29
|
+
assert migration.include?("ActiveRecord::Migration[5.0]\n")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# generator_spec gem requires such block definition :(
|
|
33
|
+
#
|
|
34
|
+
# rubocop:disable Style/BlockDelimiters
|
|
35
|
+
expect(destination_root).to(have_structure {
|
|
36
|
+
directory "config" do
|
|
37
|
+
directory "initializers" do
|
|
38
|
+
file "doorkeeper.rb" do
|
|
39
|
+
contains " use_polymorphic_resource_owner"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
})
|
|
44
|
+
# rubocop:enable Style/BlockDelimiters
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
data/spec/lib/config_spec.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require "spec_helper"
|
|
4
4
|
|
|
5
5
|
describe Doorkeeper, "configuration" do
|
|
6
|
-
subject { Doorkeeper.
|
|
6
|
+
subject { Doorkeeper.config }
|
|
7
7
|
|
|
8
8
|
describe "resource_owner_authenticator" do
|
|
9
9
|
it "sets the block that is accessible via authenticate_resource_owner" do
|
|
@@ -328,7 +328,7 @@ describe Doorkeeper, "configuration" do
|
|
|
328
328
|
|
|
329
329
|
describe "enable_application_owner" do
|
|
330
330
|
it "is disabled by default" do
|
|
331
|
-
expect(Doorkeeper.
|
|
331
|
+
expect(Doorkeeper.config.enable_application_owner?).not_to eq(true)
|
|
332
332
|
end
|
|
333
333
|
|
|
334
334
|
context "when enabled without confirmation" do
|
|
@@ -344,7 +344,7 @@ describe Doorkeeper, "configuration" do
|
|
|
344
344
|
end
|
|
345
345
|
|
|
346
346
|
it "Doorkeeper.configuration.confirm_application_owner? returns false" do
|
|
347
|
-
expect(Doorkeeper.
|
|
347
|
+
expect(Doorkeeper.config.confirm_application_owner?).not_to eq(true)
|
|
348
348
|
end
|
|
349
349
|
end
|
|
350
350
|
|
|
@@ -361,14 +361,14 @@ describe Doorkeeper, "configuration" do
|
|
|
361
361
|
end
|
|
362
362
|
|
|
363
363
|
it "Doorkeeper.configuration.confirm_application_owner? returns true" do
|
|
364
|
-
expect(Doorkeeper.
|
|
364
|
+
expect(Doorkeeper.config.confirm_application_owner?).to eq(true)
|
|
365
365
|
end
|
|
366
366
|
end
|
|
367
367
|
end
|
|
368
368
|
|
|
369
369
|
describe "realm" do
|
|
370
370
|
it "is 'Doorkeeper' by default" do
|
|
371
|
-
expect(Doorkeeper.
|
|
371
|
+
expect(Doorkeeper.config.realm).to eq("Doorkeeper")
|
|
372
372
|
end
|
|
373
373
|
|
|
374
374
|
it "can change the value" do
|
|
@@ -383,7 +383,7 @@ describe Doorkeeper, "configuration" do
|
|
|
383
383
|
|
|
384
384
|
describe "grant_flows" do
|
|
385
385
|
it "is set to all grant flows by default" do
|
|
386
|
-
expect(Doorkeeper.
|
|
386
|
+
expect(Doorkeeper.config.grant_flows)
|
|
387
387
|
.to eq(%w[authorization_code client_credentials])
|
|
388
388
|
end
|
|
389
389
|
|
|
@@ -454,13 +454,13 @@ describe Doorkeeper, "configuration" do
|
|
|
454
454
|
end
|
|
455
455
|
|
|
456
456
|
it "raises an exception when configuration is not set" do
|
|
457
|
-
old_config = Doorkeeper.
|
|
457
|
+
old_config = Doorkeeper.config
|
|
458
458
|
Doorkeeper.module_eval do
|
|
459
459
|
@config = nil
|
|
460
460
|
end
|
|
461
461
|
|
|
462
462
|
expect do
|
|
463
|
-
Doorkeeper.
|
|
463
|
+
Doorkeeper.config
|
|
464
464
|
end.to raise_error Doorkeeper::MissingConfiguration
|
|
465
465
|
|
|
466
466
|
Doorkeeper.module_eval do
|
|
@@ -527,13 +527,13 @@ describe Doorkeeper, "configuration" do
|
|
|
527
527
|
end
|
|
528
528
|
end
|
|
529
529
|
|
|
530
|
-
it { expect(Doorkeeper.
|
|
530
|
+
it { expect(Doorkeeper.config.base_controller).to eq("ApplicationController") }
|
|
531
531
|
end
|
|
532
532
|
end
|
|
533
533
|
|
|
534
534
|
describe "base_metal_controller" do
|
|
535
535
|
context "default" do
|
|
536
|
-
it { expect(Doorkeeper.
|
|
536
|
+
it { expect(Doorkeeper.config.base_metal_controller).to eq("ActionController::API") }
|
|
537
537
|
end
|
|
538
538
|
|
|
539
539
|
context "custom" do
|
|
@@ -565,6 +565,10 @@ describe Doorkeeper, "configuration" do
|
|
|
565
565
|
expect(model).to receive(:establish_connection)
|
|
566
566
|
end
|
|
567
567
|
|
|
568
|
+
expect(Kernel).to receive(:warn).with(
|
|
569
|
+
/\[DOORKEEPER\] active_record_options has been deprecated and will soon be removed/,
|
|
570
|
+
)
|
|
571
|
+
|
|
568
572
|
Doorkeeper.configure do
|
|
569
573
|
orm DOORKEEPER_ORM
|
|
570
574
|
active_record_options(
|
|
@@ -641,6 +645,21 @@ describe Doorkeeper, "configuration" do
|
|
|
641
645
|
end
|
|
642
646
|
end
|
|
643
647
|
|
|
648
|
+
describe "token_lookup_batch_size" do
|
|
649
|
+
it "uses default doorkeeper value" do
|
|
650
|
+
expect(subject.token_lookup_batch_size).to eq(10_000)
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
it "can change the value" do
|
|
654
|
+
Doorkeeper.configure do
|
|
655
|
+
orm DOORKEEPER_ORM
|
|
656
|
+
token_lookup_batch_size 100_000
|
|
657
|
+
end
|
|
658
|
+
|
|
659
|
+
expect(subject.token_lookup_batch_size).to eq(100_000)
|
|
660
|
+
end
|
|
661
|
+
end
|
|
662
|
+
|
|
644
663
|
describe "strict_content_type" do
|
|
645
664
|
it "is false by default" do
|
|
646
665
|
expect(subject.enforce_content_type).to eq(false)
|
|
@@ -658,7 +677,7 @@ describe Doorkeeper, "configuration" do
|
|
|
658
677
|
|
|
659
678
|
describe "handle_auth_errors" do
|
|
660
679
|
it "is set to render by default" do
|
|
661
|
-
expect(Doorkeeper.
|
|
680
|
+
expect(Doorkeeper.config.handle_auth_errors).to eq(:render)
|
|
662
681
|
end
|
|
663
682
|
it "can change the value" do
|
|
664
683
|
Doorkeeper.configure do
|
|
@@ -13,7 +13,7 @@ describe "Revocable" do
|
|
|
13
13
|
it "updates :revoked_at attribute with current time" do
|
|
14
14
|
utc = double utc: double
|
|
15
15
|
clock = double now: utc
|
|
16
|
-
expect(subject).to receive(:
|
|
16
|
+
expect(subject).to receive(:update_column).with(:revoked_at, clock.now.utc)
|
|
17
17
|
subject.revoke(clock)
|
|
18
18
|
end
|
|
19
19
|
end
|
|
@@ -36,8 +36,7 @@ describe "Revocable" do
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
describe :revoke_previous_refresh_token! do
|
|
39
|
-
it "revokes the previous token if
|
|
40
|
-
`previous_refresh_token` attribute" do
|
|
39
|
+
it "revokes the previous token if exists and resets the `previous_refresh_token` attribute" do
|
|
41
40
|
previous_token = FactoryBot.create(
|
|
42
41
|
:access_token,
|
|
43
42
|
refresh_token: "refresh_token",
|
|
@@ -33,6 +33,14 @@ describe "Doorkeeper::Models::Scopes" do
|
|
|
33
33
|
subject.scopes = %w[private admin]
|
|
34
34
|
expect(subject.scopes_string).to eq("private admin")
|
|
35
35
|
end
|
|
36
|
+
|
|
37
|
+
it "ignores duplicated scopes" do
|
|
38
|
+
subject.scopes = %w[private admin admin]
|
|
39
|
+
expect(subject.scopes_string).to eq("private admin")
|
|
40
|
+
|
|
41
|
+
subject.scopes = "private admin admin"
|
|
42
|
+
expect(subject.scopes_string).to eq("private admin")
|
|
43
|
+
end
|
|
36
44
|
end
|
|
37
45
|
|
|
38
46
|
describe :scopes_string do
|