doorkeeper 5.2.6 → 5.3.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/Appraisals +2 -2
- data/CHANGELOG.md +15 -14
- data/Gemfile +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +2 -2
- data/app/controllers/doorkeeper/application_metal_controller.rb +2 -2
- data/app/controllers/doorkeeper/applications_controller.rb +3 -3
- data/app/controllers/doorkeeper/authorizations_controller.rb +2 -2
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +3 -3
- data/gemfiles/rails_5_0.gemfile +2 -2
- data/gemfiles/rails_5_1.gemfile +2 -2
- data/gemfiles/rails_5_2.gemfile +2 -2
- data/gemfiles/rails_6_0.gemfile +2 -2
- data/gemfiles/rails_master.gemfile +2 -2
- data/lib/doorkeeper.rb +2 -3
- data/lib/doorkeeper/config.rb +71 -39
- data/lib/doorkeeper/grape/helpers.rb +1 -1
- data/lib/doorkeeper/helpers/controller.rb +10 -8
- data/lib/doorkeeper/models/access_grant_mixin.rb +7 -6
- data/lib/doorkeeper/models/access_token_mixin.rb +55 -18
- data/lib/doorkeeper/models/application_mixin.rb +3 -3
- data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
- data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
- data/lib/doorkeeper/models/concerns/revocable.rb +0 -27
- data/lib/doorkeeper/oauth/authorization/code.rb +4 -4
- data/lib/doorkeeper/oauth/authorization/token.rb +9 -6
- data/lib/doorkeeper/oauth/authorization_code_request.rb +13 -6
- data/lib/doorkeeper/oauth/base_request.rb +8 -4
- data/lib/doorkeeper/oauth/client.rb +7 -8
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +16 -9
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +7 -7
- data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +4 -4
- data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
- data/lib/doorkeeper/oauth/code_response.rb +2 -2
- data/lib/doorkeeper/oauth/error.rb +1 -1
- data/lib/doorkeeper/oauth/error_response.rb +5 -5
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +7 -5
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +8 -5
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +1 -1
- data/lib/doorkeeper/oauth/invalid_request_response.rb +3 -3
- data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -2
- data/lib/doorkeeper/oauth/password_access_token_request.rb +3 -3
- data/lib/doorkeeper/oauth/pre_authorization.rb +7 -5
- data/lib/doorkeeper/oauth/refresh_token_request.rb +5 -5
- data/lib/doorkeeper/oauth/token.rb +2 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +6 -6
- data/lib/doorkeeper/orm/active_record.rb +3 -3
- data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
- data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
- data/lib/doorkeeper/orm/active_record/application.rb +3 -155
- data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +53 -0
- data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +47 -0
- data/lib/doorkeeper/orm/active_record/mixins/application.rb +128 -0
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +3 -3
- data/lib/doorkeeper/rails/helpers.rb +4 -4
- data/lib/doorkeeper/rails/routes.rb +5 -7
- data/lib/doorkeeper/rake/db.rake +3 -3
- data/lib/doorkeeper/request.rb +1 -1
- data/lib/doorkeeper/request/authorization_code.rb +3 -3
- data/lib/doorkeeper/request/client_credentials.rb +2 -2
- data/lib/doorkeeper/request/password.rb +2 -2
- data/lib/doorkeeper/request/refresh_token.rb +3 -3
- data/lib/doorkeeper/server.rb +1 -1
- data/lib/doorkeeper/stale_records_cleaner.rb +1 -1
- data/lib/doorkeeper/version.rb +2 -2
- data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
- data/lib/generators/doorkeeper/migration_generator.rb +1 -1
- data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +2 -2
- data/lib/generators/doorkeeper/templates/initializer.rb +39 -8
- data/spec/controllers/application_metal_controller_spec.rb +1 -1
- data/spec/controllers/applications_controller_spec.rb +3 -2
- data/spec/controllers/authorizations_controller_spec.rb +18 -18
- data/spec/controllers/protected_resources_controller_spec.rb +25 -17
- data/spec/controllers/token_info_controller_spec.rb +1 -1
- data/spec/controllers/tokens_controller_spec.rb +1 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -3
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +1 -1
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +1 -1
- data/spec/generators/install_generator_spec.rb +1 -1
- data/spec/generators/previous_refresh_token_generator_spec.rb +2 -2
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +61 -21
- data/spec/lib/doorkeeper_spec.rb +1 -1
- data/spec/lib/models/revocable_spec.rb +3 -3
- data/spec/lib/oauth/authorization_code_request_spec.rb +127 -125
- data/spec/lib/oauth/base_request_spec.rb +160 -158
- data/spec/lib/oauth/base_response_spec.rb +27 -29
- data/spec/lib/oauth/client/credentials_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials/creator_spec.rb +42 -5
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +12 -12
- data/spec/lib/oauth/client_credentials/validation_spec.rb +4 -4
- data/spec/lib/oauth/client_credentials_integration_spec.rb +16 -18
- data/spec/lib/oauth/client_credentials_request_spec.rb +78 -80
- data/spec/lib/oauth/client_spec.rb +26 -26
- data/spec/lib/oauth/code_request_spec.rb +34 -34
- data/spec/lib/oauth/code_response_spec.rb +21 -25
- data/spec/lib/oauth/error_response_spec.rb +42 -44
- data/spec/lib/oauth/error_spec.rb +12 -14
- data/spec/lib/oauth/forbidden_token_response_spec.rb +11 -13
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +30 -18
- data/spec/lib/oauth/invalid_request_response_spec.rb +48 -50
- data/spec/lib/oauth/invalid_token_response_spec.rb +32 -34
- data/spec/lib/oauth/password_access_token_request_spec.rb +145 -147
- data/spec/lib/oauth/pre_authorization_spec.rb +159 -161
- data/spec/lib/oauth/refresh_token_request_spec.rb +138 -139
- data/spec/lib/oauth/scopes_spec.rb +104 -106
- data/spec/lib/oauth/token_request_spec.rb +115 -111
- data/spec/lib/oauth/token_response_spec.rb +71 -73
- data/spec/lib/oauth/token_spec.rb +121 -123
- data/spec/models/doorkeeper/access_grant_spec.rb +3 -5
- data/spec/models/doorkeeper/access_token_spec.rb +7 -7
- data/spec/models/doorkeeper/application_spec.rb +295 -373
- data/spec/requests/applications/applications_request_spec.rb +1 -1
- data/spec/requests/endpoints/authorization_spec.rb +5 -3
- data/spec/requests/flows/authorization_code_spec.rb +34 -22
- data/spec/requests/flows/client_credentials_spec.rb +1 -1
- data/spec/requests/flows/password_spec.rb +32 -12
- data/spec/requests/flows/refresh_token_spec.rb +19 -19
- data/spec/requests/flows/revoke_token_spec.rb +18 -12
- data/spec/spec_helper.rb +1 -4
- data/spec/support/shared/controllers_shared_context.rb +33 -23
- data/spec/validators/redirect_uri_validator_spec.rb +1 -1
- metadata +6 -5
- data/spec/support/http_method_shim.rb +0 -29
@@ -28,9 +28,11 @@ describe "doorkeeper authorize filter" do
|
|
28
28
|
|
29
29
|
let(:token_string) { "1A2BC3" }
|
30
30
|
let(:token) do
|
31
|
-
double(
|
32
|
-
|
33
|
-
|
31
|
+
double(
|
32
|
+
Doorkeeper::AccessToken,
|
33
|
+
acceptable?: true, previous_refresh_token: "",
|
34
|
+
revoke_previous_refresh_token!: true,
|
35
|
+
)
|
34
36
|
end
|
35
37
|
|
36
38
|
it "access_token param" do
|
@@ -108,13 +110,15 @@ describe "doorkeeper authorize filter" do
|
|
108
110
|
let(:token_string) { "1A2DUWE" }
|
109
111
|
|
110
112
|
it "allows if the token has particular scopes" do
|
111
|
-
token = double(
|
112
|
-
|
113
|
-
|
114
|
-
|
113
|
+
token = double(
|
114
|
+
Doorkeeper::AccessToken,
|
115
|
+
accessible?: true, scopes: %w[write public],
|
116
|
+
previous_refresh_token: "",
|
117
|
+
revoke_previous_refresh_token!: true,
|
118
|
+
)
|
115
119
|
expect(token).to receive(:acceptable?).with([:write]).and_return(true)
|
116
120
|
expect(
|
117
|
-
Doorkeeper::AccessToken
|
121
|
+
Doorkeeper::AccessToken,
|
118
122
|
).to receive(:by_token).with(token_string).and_return(token)
|
119
123
|
|
120
124
|
get :index, params: { access_token: token_string }
|
@@ -122,12 +126,14 @@ describe "doorkeeper authorize filter" do
|
|
122
126
|
end
|
123
127
|
|
124
128
|
it "does not allow if the token does not include given scope" do
|
125
|
-
token = double(
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
+
token = double(
|
130
|
+
Doorkeeper::AccessToken,
|
131
|
+
accessible?: true, scopes: ["public"], revoked?: false,
|
132
|
+
expired?: false, previous_refresh_token: "",
|
133
|
+
revoke_previous_refresh_token!: true,
|
134
|
+
)
|
129
135
|
expect(
|
130
|
-
Doorkeeper::AccessToken
|
136
|
+
Doorkeeper::AccessToken,
|
131
137
|
).to receive(:by_token).with(token_string).and_return(token)
|
132
138
|
expect(token).to receive(:acceptable?).with([:write]).and_return(false)
|
133
139
|
|
@@ -224,10 +230,12 @@ describe "doorkeeper authorize filter" do
|
|
224
230
|
end
|
225
231
|
|
226
232
|
let(:token) do
|
227
|
-
double(
|
228
|
-
|
229
|
-
|
230
|
-
|
233
|
+
double(
|
234
|
+
Doorkeeper::AccessToken,
|
235
|
+
accessible?: true, scopes: ["public"], revoked?: false,
|
236
|
+
expired?: false, previous_refresh_token: "",
|
237
|
+
revoke_previous_refresh_token!: true,
|
238
|
+
)
|
231
239
|
end
|
232
240
|
|
233
241
|
let(:token_string) { "1A2DUWE" }
|
@@ -142,7 +142,7 @@ describe Doorkeeper::TokensController do
|
|
142
142
|
allow(I18n).to receive(:translate)
|
143
143
|
.with(
|
144
144
|
custom_message,
|
145
|
-
hash_including(scope: %i[doorkeeper errors messages])
|
145
|
+
hash_including(scope: %i[doorkeeper errors messages]),
|
146
146
|
)
|
147
147
|
.and_return("Authorization custom message")
|
148
148
|
|
@@ -25,14 +25,14 @@ class CreateDoorkeeperTables < ActiveRecord::Migration[4.2]
|
|
25
25
|
t.text :redirect_uri, null: false
|
26
26
|
t.datetime :created_at, null: false
|
27
27
|
t.datetime :revoked_at
|
28
|
-
t.string :scopes,
|
28
|
+
t.string :scopes, null: false, default: ""
|
29
29
|
end
|
30
30
|
|
31
31
|
add_index :oauth_access_grants, :token, unique: true
|
32
32
|
add_foreign_key(
|
33
33
|
:oauth_access_grants,
|
34
34
|
:oauth_applications,
|
35
|
-
column: :application_id
|
35
|
+
column: :application_id,
|
36
36
|
)
|
37
37
|
|
38
38
|
create_table :oauth_access_tokens do |t|
|
@@ -59,7 +59,7 @@ class CreateDoorkeeperTables < ActiveRecord::Migration[4.2]
|
|
59
59
|
add_foreign_key(
|
60
60
|
:oauth_access_tokens,
|
61
61
|
:oauth_applications,
|
62
|
-
column: :application_id
|
62
|
+
column: :application_id,
|
63
63
|
)
|
64
64
|
|
65
65
|
# Uncomment below to ensure a valid reference to the resource owner's table
|
@@ -7,7 +7,7 @@ class AddConfidentialToApplications < ActiveRecord::Migration[5.1]
|
|
7
7
|
:confidential,
|
8
8
|
:boolean,
|
9
9
|
null: false,
|
10
|
-
default: true # maintaining backwards compatibility: require secrets
|
10
|
+
default: true, # maintaining backwards compatibility: require secrets
|
11
11
|
)
|
12
12
|
end
|
13
13
|
end
|
@@ -16,7 +16,7 @@ describe "Doorkeeper::InstallGenerator" do
|
|
16
16
|
FileUtils.mkdir(::File.expand_path("db", Pathname(destination_root)))
|
17
17
|
FileUtils.copy_file(
|
18
18
|
::File.expand_path("../templates/routes.rb", __FILE__),
|
19
|
-
::File.expand_path("config/routes.rb", Pathname.new(destination_root))
|
19
|
+
::File.expand_path("config/routes.rb", Pathname.new(destination_root)),
|
20
20
|
)
|
21
21
|
run_generator
|
22
22
|
end
|
@@ -14,7 +14,7 @@ describe "Doorkeeper::PreviousRefreshTokenGenerator" do
|
|
14
14
|
prepare_destination
|
15
15
|
|
16
16
|
allow_any_instance_of(Doorkeeper::PreviousRefreshTokenGenerator).to(
|
17
|
-
receive(:no_previous_refresh_token_column?).and_return(true)
|
17
|
+
receive(:no_previous_refresh_token_column?).and_return(true),
|
18
18
|
)
|
19
19
|
end
|
20
20
|
|
@@ -32,7 +32,7 @@ describe "Doorkeeper::PreviousRefreshTokenGenerator" do
|
|
32
32
|
context "already exist" do
|
33
33
|
it "does not create a migration" do
|
34
34
|
allow_any_instance_of(Doorkeeper::PreviousRefreshTokenGenerator).to(
|
35
|
-
receive(:no_previous_refresh_token_column?).and_call_original
|
35
|
+
receive(:no_previous_refresh_token_column?).and_call_original,
|
36
36
|
)
|
37
37
|
|
38
38
|
run_generator
|
data/spec/lib/config_spec.rb
CHANGED
@@ -22,7 +22,7 @@ describe Doorkeeper, "configuration" do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
expect(Rails.logger).to receive(:warn).with(
|
25
|
-
I18n.t("doorkeeper.errors.messages.resource_owner_authenticator_not_configured")
|
25
|
+
I18n.t("doorkeeper.errors.messages.resource_owner_authenticator_not_configured"),
|
26
26
|
)
|
27
27
|
subject.authenticate_resource_owner.call(nil)
|
28
28
|
end
|
@@ -45,7 +45,7 @@ describe Doorkeeper, "configuration" do
|
|
45
45
|
end
|
46
46
|
|
47
47
|
expect(Rails.logger).to receive(:warn).with(
|
48
|
-
I18n.t("doorkeeper.errors.messages.credential_flow_not_configured")
|
48
|
+
I18n.t("doorkeeper.errors.messages.credential_flow_not_configured"),
|
49
49
|
)
|
50
50
|
subject.resource_owner_from_credentials.call(nil)
|
51
51
|
end
|
@@ -471,7 +471,7 @@ describe Doorkeeper, "configuration" do
|
|
471
471
|
describe "access_token_generator" do
|
472
472
|
it "is 'Doorkeeper::OAuth::Helpers::UniqueToken' by default" do
|
473
473
|
expect(Doorkeeper.configuration.access_token_generator).to(
|
474
|
-
eq("Doorkeeper::OAuth::Helpers::UniqueToken")
|
474
|
+
eq("Doorkeeper::OAuth::Helpers::UniqueToken"),
|
475
475
|
)
|
476
476
|
end
|
477
477
|
|
@@ -549,6 +549,8 @@ describe Doorkeeper, "configuration" do
|
|
549
549
|
end
|
550
550
|
|
551
551
|
if DOORKEEPER_ORM == :active_record
|
552
|
+
class FakeCustomModel; end
|
553
|
+
|
552
554
|
describe "active_record_options" do
|
553
555
|
let(:models) { [Doorkeeper::AccessGrant, Doorkeeper::AccessToken, Doorkeeper::Application] }
|
554
556
|
|
@@ -566,40 +568,76 @@ describe Doorkeeper, "configuration" do
|
|
566
568
|
Doorkeeper.configure do
|
567
569
|
orm DOORKEEPER_ORM
|
568
570
|
active_record_options(
|
569
|
-
establish_connection: Rails.configuration.database_configuration[Rails.env]
|
571
|
+
establish_connection: Rails.configuration.database_configuration[Rails.env],
|
570
572
|
)
|
571
573
|
end
|
572
574
|
end
|
573
575
|
end
|
574
|
-
end
|
575
576
|
|
576
|
-
|
577
|
-
|
578
|
-
|
577
|
+
describe "access_token_class" do
|
578
|
+
it "uses default doorkeeper value" do
|
579
|
+
expect(subject.access_token_class).to eq("Doorkeeper::AccessToken")
|
580
|
+
expect(subject.access_token_model).to be(Doorkeeper::AccessToken)
|
581
|
+
end
|
582
|
+
|
583
|
+
it "can change the value" do
|
584
|
+
Doorkeeper.configure do
|
585
|
+
orm DOORKEEPER_ORM
|
586
|
+
access_token_class "FakeCustomModel"
|
587
|
+
end
|
588
|
+
|
589
|
+
expect(subject.access_token_class).to eq("FakeCustomModel")
|
590
|
+
expect(subject.access_token_model).to be(FakeCustomModel)
|
591
|
+
end
|
579
592
|
end
|
580
593
|
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
594
|
+
describe "access_grant_class" do
|
595
|
+
it "uses default doorkeeper value" do
|
596
|
+
expect(subject.access_grant_class).to eq("Doorkeeper::AccessGrant")
|
597
|
+
expect(subject.access_grant_model).to be(Doorkeeper::AccessGrant)
|
585
598
|
end
|
586
599
|
|
587
|
-
|
600
|
+
it "can change the value" do
|
601
|
+
Doorkeeper.configure do
|
602
|
+
orm DOORKEEPER_ORM
|
603
|
+
access_grant_class "FakeCustomModel"
|
604
|
+
end
|
605
|
+
|
606
|
+
expect(subject.access_grant_class).to eq("FakeCustomModel")
|
607
|
+
expect(subject.access_grant_model).to be(FakeCustomModel)
|
608
|
+
end
|
609
|
+
end
|
610
|
+
|
611
|
+
describe "application_class" do
|
612
|
+
it "uses default doorkeeper value" do
|
613
|
+
expect(subject.application_class).to eq("Doorkeeper::Application")
|
614
|
+
expect(subject.application_model).to be(Doorkeeper::Application)
|
615
|
+
end
|
616
|
+
|
617
|
+
it "can change the value" do
|
618
|
+
Doorkeeper.configure do
|
619
|
+
orm DOORKEEPER_ORM
|
620
|
+
application_class "FakeCustomModel"
|
621
|
+
end
|
622
|
+
|
623
|
+
expect(subject.application_class).to eq("FakeCustomModel")
|
624
|
+
expect(subject.application_model).to be(FakeCustomModel)
|
625
|
+
end
|
588
626
|
end
|
589
627
|
end
|
590
628
|
|
591
|
-
describe "
|
592
|
-
it "
|
593
|
-
expect(subject.
|
629
|
+
describe "api_only" do
|
630
|
+
it "is false by default" do
|
631
|
+
expect(subject.api_only).to eq(false)
|
594
632
|
end
|
595
633
|
|
596
634
|
it "can change the value" do
|
597
635
|
Doorkeeper.configure do
|
598
636
|
orm DOORKEEPER_ORM
|
599
|
-
|
637
|
+
api_only
|
600
638
|
end
|
601
639
|
|
602
|
-
expect(subject.
|
640
|
+
expect(subject.api_only).to eq(true)
|
603
641
|
end
|
604
642
|
end
|
605
643
|
|
@@ -666,8 +704,10 @@ describe Doorkeeper, "configuration" do
|
|
666
704
|
Doorkeeper.configure do
|
667
705
|
hash_token_secrets using: "Doorkeeper::SecretStoring::BCrypt"
|
668
706
|
end
|
669
|
-
end.to raise_error(
|
670
|
-
|
707
|
+
end.to raise_error(
|
708
|
+
ArgumentError,
|
709
|
+
/can only be used for storing application secrets/,
|
710
|
+
)
|
671
711
|
end
|
672
712
|
end
|
673
713
|
|
@@ -744,7 +784,7 @@ describe Doorkeeper, "configuration" do
|
|
744
784
|
describe "options deprecation" do
|
745
785
|
it "prints a warning message when an option is deprecated" do
|
746
786
|
expect(Kernel).to receive(:warn).with(
|
747
|
-
"[DOORKEEPER] native_redirect_uri has been deprecated and will soon be removed"
|
787
|
+
"[DOORKEEPER] native_redirect_uri has been deprecated and will soon be removed",
|
748
788
|
)
|
749
789
|
Doorkeeper.configure do
|
750
790
|
native_redirect_uri "urn:ietf:wg:oauth:2.0:oob"
|
data/spec/lib/doorkeeper_spec.rb
CHANGED
@@ -7,7 +7,7 @@ describe Doorkeeper do
|
|
7
7
|
let(:request) { double }
|
8
8
|
|
9
9
|
it "calls OAuth::Token#authenticate" do
|
10
|
-
token_strategies = Doorkeeper.
|
10
|
+
token_strategies = Doorkeeper.config.access_token_methods
|
11
11
|
|
12
12
|
expect(Doorkeeper::OAuth::Token).to receive(:authenticate)
|
13
13
|
.with(request, *token_strategies)
|
@@ -40,15 +40,15 @@ describe "Revocable" do
|
|
40
40
|
`previous_refresh_token` attribute" do
|
41
41
|
previous_token = FactoryBot.create(
|
42
42
|
:access_token,
|
43
|
-
refresh_token: "refresh_token"
|
43
|
+
refresh_token: "refresh_token",
|
44
44
|
)
|
45
45
|
current_token = FactoryBot.create(
|
46
46
|
:access_token,
|
47
|
-
previous_refresh_token: previous_token.refresh_token
|
47
|
+
previous_refresh_token: previous_token.refresh_token,
|
48
48
|
)
|
49
49
|
|
50
50
|
expect_any_instance_of(
|
51
|
-
Doorkeeper::AccessToken
|
51
|
+
Doorkeeper::AccessToken,
|
52
52
|
).to receive(:revoke).and_call_original
|
53
53
|
current_token.revoke_previous_refresh_token!
|
54
54
|
|
@@ -2,167 +2,169 @@
|
|
2
2
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
5
|
+
describe Doorkeeper::OAuth::AuthorizationCodeRequest do
|
6
|
+
let(:server) do
|
7
|
+
double :server,
|
8
|
+
access_token_expires_in: 2.days,
|
9
|
+
refresh_token_enabled?: false,
|
10
|
+
custom_access_token_expires_in: lambda { |context|
|
11
|
+
context.grant_type == Doorkeeper::OAuth::AUTHORIZATION_CODE ? 1234 : nil
|
12
|
+
}
|
13
|
+
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
let(:grant) { FactoryBot.create :access_grant }
|
16
|
+
let(:client) { grant.application }
|
17
|
+
let(:redirect_uri) { client.redirect_uri }
|
18
|
+
let(:params) { { redirect_uri: redirect_uri } }
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
before do
|
21
|
+
allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(true)
|
22
|
+
end
|
24
23
|
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
subject do
|
25
|
+
described_class.new(server, grant, client, params)
|
26
|
+
end
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
it "issues a new token for the client" do
|
29
|
+
expect do
|
30
|
+
subject.authorize
|
31
|
+
end.to change { client.reload.access_tokens.count }.by(1)
|
33
32
|
|
34
|
-
|
35
|
-
|
33
|
+
expect(client.reload.access_tokens.max_by(&:created_at).expires_in).to eq(1234)
|
34
|
+
end
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
it "issues the token with same grant's scopes" do
|
37
|
+
subject.authorize
|
38
|
+
expect(Doorkeeper::AccessToken.last.scopes).to eq(grant.scopes)
|
39
|
+
end
|
41
40
|
|
42
|
-
|
43
|
-
|
44
|
-
|
41
|
+
it "revokes the grant" do
|
42
|
+
expect { subject.authorize }.to(change { grant.reload.accessible? })
|
43
|
+
end
|
45
44
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
45
|
+
it "requires the grant to be accessible" do
|
46
|
+
grant.revoke
|
47
|
+
subject.validate
|
48
|
+
expect(subject.error).to eq(:invalid_grant)
|
49
|
+
end
|
51
50
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
51
|
+
it "requires the grant" do
|
52
|
+
subject.grant = nil
|
53
|
+
subject.validate
|
54
|
+
expect(subject.error).to eq(:invalid_grant)
|
55
|
+
end
|
57
56
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
57
|
+
it "requires the client" do
|
58
|
+
subject.client = nil
|
59
|
+
subject.validate
|
60
|
+
expect(subject.error).to eq(:invalid_client)
|
61
|
+
end
|
63
62
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
63
|
+
it "requires the redirect_uri" do
|
64
|
+
subject.redirect_uri = nil
|
65
|
+
subject.validate
|
66
|
+
expect(subject.error).to eq(:invalid_request)
|
67
|
+
expect(subject.missing_param).to eq(:redirect_uri)
|
68
|
+
end
|
70
69
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
70
|
+
it "invalid code_verifier param because server does not support pkce" do
|
71
|
+
# Some other ORMs work relies on #respond_to? so it's not a good idea to stub it :\
|
72
|
+
allow_any_instance_of(Doorkeeper::AccessGrant).to receive(:respond_to?).with(anything).and_call_original
|
73
|
+
allow_any_instance_of(Doorkeeper::AccessGrant).to receive(:respond_to?).with(:code_challenge).and_return(false)
|
75
74
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
75
|
+
subject.code_verifier = "a45a9fea-0676-477e-95b1-a40f72ac3cfb"
|
76
|
+
subject.validate
|
77
|
+
expect(subject.error).to eq(:invalid_request)
|
78
|
+
expect(subject.invalid_request_reason).to eq(:not_support_pkce)
|
79
|
+
end
|
81
80
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
81
|
+
it "matches the redirect_uri with grant's one" do
|
82
|
+
subject.redirect_uri = "http://other.com"
|
83
|
+
subject.validate
|
84
|
+
expect(subject.error).to eq(:invalid_grant)
|
85
|
+
end
|
87
86
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
87
|
+
it "matches the client with grant's one" do
|
88
|
+
subject.client = FactoryBot.create :application
|
89
|
+
subject.validate
|
90
|
+
expect(subject.error).to eq(:invalid_grant)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "skips token creation if there is a matching one reusable" do
|
94
|
+
scopes = grant.scopes
|
95
|
+
|
96
|
+
Doorkeeper.configure do
|
97
|
+
orm DOORKEEPER_ORM
|
98
|
+
reuse_access_token
|
99
|
+
default_scopes(*scopes)
|
92
100
|
end
|
93
101
|
|
94
|
-
|
95
|
-
|
102
|
+
FactoryBot.create(
|
103
|
+
:access_token, application_id: client.id,
|
104
|
+
resource_owner_id: grant.resource_owner_id, scopes: grant.scopes.to_s,
|
105
|
+
)
|
96
106
|
|
97
|
-
|
98
|
-
|
99
|
-
reuse_access_token
|
100
|
-
default_scopes(*scopes)
|
101
|
-
end
|
107
|
+
expect { subject.authorize }.to_not(change { Doorkeeper::AccessToken.count })
|
108
|
+
end
|
102
109
|
|
103
|
-
|
104
|
-
|
110
|
+
it "creates token if there is a matching one but non reusable" do
|
111
|
+
scopes = grant.scopes
|
105
112
|
|
106
|
-
|
113
|
+
Doorkeeper.configure do
|
114
|
+
orm DOORKEEPER_ORM
|
115
|
+
reuse_access_token
|
116
|
+
default_scopes(*scopes)
|
107
117
|
end
|
108
118
|
|
109
|
-
|
110
|
-
|
119
|
+
FactoryBot.create(
|
120
|
+
:access_token, application_id: client.id,
|
121
|
+
resource_owner_id: grant.resource_owner_id, scopes: grant.scopes.to_s,
|
122
|
+
)
|
111
123
|
|
112
|
-
|
113
|
-
orm DOORKEEPER_ORM
|
114
|
-
reuse_access_token
|
115
|
-
default_scopes(*scopes)
|
116
|
-
end
|
124
|
+
allow_any_instance_of(Doorkeeper::AccessToken).to receive(:reusable?).and_return(false)
|
117
125
|
|
118
|
-
|
119
|
-
|
126
|
+
expect { subject.authorize }.to change { Doorkeeper::AccessToken.count }.by(1)
|
127
|
+
end
|
120
128
|
|
121
|
-
|
129
|
+
it "calls configured request callback methods" do
|
130
|
+
expect(Doorkeeper.configuration.before_successful_strategy_response)
|
131
|
+
.to receive(:call).with(subject).once
|
132
|
+
expect(Doorkeeper.configuration.after_successful_strategy_response)
|
133
|
+
.to receive(:call).with(subject, instance_of(Doorkeeper::OAuth::TokenResponse)).once
|
122
134
|
|
123
|
-
|
124
|
-
|
135
|
+
subject.authorize
|
136
|
+
end
|
125
137
|
|
126
|
-
|
127
|
-
|
128
|
-
.to receive(:call).with(subject).once
|
129
|
-
expect(Doorkeeper.configuration.after_successful_strategy_response)
|
130
|
-
.to receive(:call).with(subject, instance_of(Doorkeeper::OAuth::TokenResponse)).once
|
138
|
+
context "when redirect_uri contains some query params" do
|
139
|
+
let(:redirect_uri) { client.redirect_uri + "?query=q" }
|
131
140
|
|
132
|
-
|
141
|
+
it "compares only host part with grant's redirect_uri" do
|
142
|
+
subject.validate
|
143
|
+
expect(subject.error).to eq(nil)
|
133
144
|
end
|
145
|
+
end
|
134
146
|
|
135
|
-
|
136
|
-
|
147
|
+
context "when redirect_uri is not an URI" do
|
148
|
+
let(:redirect_uri) { "123d#!s" }
|
137
149
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
end
|
150
|
+
it "responds with invalid_grant" do
|
151
|
+
subject.validate
|
152
|
+
expect(subject.error).to eq(:invalid_grant)
|
142
153
|
end
|
154
|
+
end
|
143
155
|
|
144
|
-
|
145
|
-
|
156
|
+
context "when redirect_uri is the native one" do
|
157
|
+
let(:redirect_uri) { "urn:ietf:wg:oauth:2.0:oob" }
|
146
158
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
end
|
159
|
+
it "invalidates when redirect_uri of the grant is not native" do
|
160
|
+
subject.validate
|
161
|
+
expect(subject.error).to eq(:invalid_grant)
|
151
162
|
end
|
152
163
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
subject.validate
|
158
|
-
expect(subject.error).to eq(:invalid_grant)
|
159
|
-
end
|
160
|
-
|
161
|
-
it "validates when redirect_uri of the grant is also native" do
|
162
|
-
allow(grant).to receive(:redirect_uri) { redirect_uri }
|
163
|
-
subject.validate
|
164
|
-
expect(subject.error).to eq(nil)
|
165
|
-
end
|
164
|
+
it "validates when redirect_uri of the grant is also native" do
|
165
|
+
allow(grant).to receive(:redirect_uri) { redirect_uri }
|
166
|
+
subject.validate
|
167
|
+
expect(subject.error).to eq(nil)
|
166
168
|
end
|
167
169
|
end
|
168
170
|
end
|