doorkeeper 5.2.6 → 5.3.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of doorkeeper might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Appraisals +2 -2
- data/CHANGELOG.md +24 -5
- 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/authorizations_controller.rb +2 -2
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -2
- 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/config.rb +71 -38
- 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 +54 -16
- 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/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 +187 -0
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +3 -3
- data/lib/doorkeeper/orm/active_record.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/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/request.rb +1 -1
- 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/doorkeeper.rb +2 -3
- 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 -0
- 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 +62 -7
- 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 +2 -2
- 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
@@ -7,152 +7,150 @@ module Doorkeeper
|
|
7
7
|
class AccessToken
|
8
8
|
end
|
9
9
|
end
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
let(:request) { double.as_null_object }
|
12
|
+
describe Doorkeeper::OAuth::Token do
|
13
|
+
describe ".from_request" do
|
14
|
+
let(:request) { double.as_null_object }
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
let(:method) do
|
17
|
+
->(*) { "token-value" }
|
18
|
+
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
it "accepts anything that responds to #call" do
|
21
|
+
expect(method).to receive(:call).with(request)
|
22
|
+
described_class.from_request request, method
|
23
|
+
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
it "delegates methods received as symbols to described_class class" do
|
26
|
+
expect(described_class).to receive(:from_params).with(request)
|
27
|
+
described_class.from_request request, :from_params
|
28
|
+
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
it "stops at the first credentials found" do
|
31
|
+
not_called_method = double
|
32
|
+
expect(not_called_method).not_to receive(:call)
|
33
|
+
described_class.from_request request, ->(_r) {}, method, not_called_method
|
34
|
+
end
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
it "returns the credential from extractor method" do
|
37
|
+
credentials = described_class.from_request request, method
|
38
|
+
expect(credentials).to eq("token-value")
|
39
|
+
end
|
40
|
+
end
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
42
|
+
describe ".from_access_token_param" do
|
43
|
+
it "returns token from access_token parameter" do
|
44
|
+
request = double parameters: { access_token: "some-token" }
|
45
|
+
token = described_class.from_access_token_param(request)
|
46
|
+
expect(token).to eq("some-token")
|
47
|
+
end
|
48
|
+
end
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
50
|
+
describe ".from_bearer_param" do
|
51
|
+
it "returns token from bearer_token parameter" do
|
52
|
+
request = double parameters: { bearer_token: "some-token" }
|
53
|
+
token = described_class.from_bearer_param(request)
|
54
|
+
expect(token).to eq("some-token")
|
55
|
+
end
|
56
|
+
end
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
58
|
+
describe ".from_bearer_authorization" do
|
59
|
+
it "returns token from capitalized authorization bearer" do
|
60
|
+
request = double authorization: "Bearer SomeToken"
|
61
|
+
token = described_class.from_bearer_authorization(request)
|
62
|
+
expect(token).to eq("SomeToken")
|
63
|
+
end
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
65
|
+
it "returns token from lowercased authorization bearer" do
|
66
|
+
request = double authorization: "bearer SomeToken"
|
67
|
+
token = described_class.from_bearer_authorization(request)
|
68
|
+
expect(token).to eq("SomeToken")
|
69
|
+
end
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
71
|
+
it "does not return token if authorization is not bearer" do
|
72
|
+
request = double authorization: "MAC SomeToken"
|
73
|
+
token = described_class.from_bearer_authorization(request)
|
74
|
+
expect(token).to be_blank
|
75
|
+
end
|
76
|
+
end
|
77
77
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
78
|
+
describe ".from_basic_authorization" do
|
79
|
+
it "returns token from capitalized authorization basic" do
|
80
|
+
request = double authorization: "Basic #{Base64.encode64 "SomeToken:"}"
|
81
|
+
token = described_class.from_basic_authorization(request)
|
82
|
+
expect(token).to eq("SomeToken")
|
83
|
+
end
|
84
84
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
85
|
+
it "returns token from lowercased authorization basic" do
|
86
|
+
request = double authorization: "basic #{Base64.encode64 "SomeToken:"}"
|
87
|
+
token = described_class.from_basic_authorization(request)
|
88
|
+
expect(token).to eq("SomeToken")
|
89
|
+
end
|
90
90
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
91
|
+
it "does not return token if authorization is not basic" do
|
92
|
+
request = double authorization: "MAC #{Base64.encode64 "SomeToken:"}"
|
93
|
+
token = described_class.from_basic_authorization(request)
|
94
|
+
expect(token).to be_blank
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe ".authenticate" do
|
99
|
+
context "refresh tokens are disabled (default)" do
|
100
|
+
context "refresh tokens are enabled" do
|
101
|
+
it "does not revoke previous refresh_token if token was found" do
|
102
|
+
token = ->(_r) { "token" }
|
103
|
+
expect(
|
104
|
+
Doorkeeper::AccessToken,
|
105
|
+
).to receive(:by_token).with("token").and_return(token)
|
106
|
+
expect(token).not_to receive(:revoke_previous_refresh_token!)
|
107
|
+
described_class.authenticate double, token
|
95
108
|
end
|
96
109
|
end
|
97
110
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
AccessToken
|
105
|
-
).to receive(:by_token).with("token").and_return(token)
|
106
|
-
expect(token).not_to receive(:revoke_previous_refresh_token!)
|
107
|
-
Token.authenticate double, token
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
it "calls the finder if token was returned" do
|
112
|
-
token = ->(_r) { "token" }
|
113
|
-
expect(AccessToken).to receive(:by_token).with("token")
|
114
|
-
Token.authenticate double, token
|
115
|
-
end
|
116
|
-
end
|
111
|
+
it "calls the finder if token was returned" do
|
112
|
+
token = ->(_r) { "token" }
|
113
|
+
expect(Doorkeeper::AccessToken).to receive(:by_token).with("token")
|
114
|
+
described_class.authenticate double, token
|
115
|
+
end
|
116
|
+
end
|
117
117
|
|
118
|
-
|
119
|
-
|
118
|
+
context "token hashing is enabled" do
|
119
|
+
include_context "with token hashing enabled"
|
120
120
|
|
121
|
-
|
122
|
-
|
121
|
+
let(:hashed_token) { hashed_or_plain_token_func.call("token") }
|
122
|
+
let(:token) { ->(_r) { "token" } }
|
123
123
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
124
|
+
it "searches with the hashed token" do
|
125
|
+
expect(
|
126
|
+
Doorkeeper::AccessToken,
|
127
|
+
).to receive(:find_by).with(token: hashed_token).and_return(token)
|
128
|
+
described_class.authenticate double, token
|
129
|
+
end
|
130
|
+
end
|
131
131
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
it "revokes previous refresh_token if token was found" do
|
141
|
-
token = ->(_r) { "token" }
|
142
|
-
expect(
|
143
|
-
AccessToken
|
144
|
-
).to receive(:by_token).with("token").and_return(token)
|
145
|
-
expect(token).to receive(:revoke_previous_refresh_token!)
|
146
|
-
Token.authenticate double, token
|
147
|
-
end
|
148
|
-
|
149
|
-
it "calls the finder if token was returned" do
|
150
|
-
token = ->(_r) { "token" }
|
151
|
-
expect(AccessToken).to receive(:by_token).with("token")
|
152
|
-
Token.authenticate double, token
|
153
|
-
end
|
132
|
+
context "refresh tokens are enabled" do
|
133
|
+
before do
|
134
|
+
Doorkeeper.configure do
|
135
|
+
orm DOORKEEPER_ORM
|
136
|
+
use_refresh_token
|
154
137
|
end
|
155
138
|
end
|
139
|
+
|
140
|
+
it "revokes previous refresh_token if token was found" do
|
141
|
+
token = ->(_r) { "token" }
|
142
|
+
expect(
|
143
|
+
Doorkeeper::AccessToken,
|
144
|
+
).to receive(:by_token).with("token").and_return(token)
|
145
|
+
expect(token).to receive(:revoke_previous_refresh_token!)
|
146
|
+
described_class.authenticate double, token
|
147
|
+
end
|
148
|
+
|
149
|
+
it "calls the finder if token was returned" do
|
150
|
+
token = ->(_r) { "token" }
|
151
|
+
expect(Doorkeeper::AccessToken).to receive(:by_token).with("token")
|
152
|
+
described_class.authenticate double, token
|
153
|
+
end
|
156
154
|
end
|
157
155
|
end
|
158
156
|
end
|
@@ -81,9 +81,7 @@ describe Doorkeeper::AccessGrant do
|
|
81
81
|
)
|
82
82
|
|
83
83
|
# Not all the ORM support :id PK
|
84
|
-
if grant.respond_to?(:id)
|
85
|
-
expect(clazz.by_token(plain_text_token).id).to eq(grant.id)
|
86
|
-
end
|
84
|
+
expect(clazz.by_token(plain_text_token).id).to eq(grant.id) if grant.respond_to?(:id)
|
87
85
|
|
88
86
|
# And it modifies the token value
|
89
87
|
grant.reload
|
@@ -141,7 +139,7 @@ describe Doorkeeper::AccessGrant do
|
|
141
139
|
it "matches application" do
|
142
140
|
access_grant_for_different_app = FactoryBot.create(
|
143
141
|
:access_grant,
|
144
|
-
default_attributes.merge(application: FactoryBot.create(:application))
|
142
|
+
default_attributes.merge(application: FactoryBot.create(:application)),
|
145
143
|
)
|
146
144
|
|
147
145
|
described_class.revoke_all_for(application.id, resource_owner)
|
@@ -152,7 +150,7 @@ describe Doorkeeper::AccessGrant do
|
|
152
150
|
it "matches resource owner" do
|
153
151
|
access_grant_for_different_owner = FactoryBot.create(
|
154
152
|
:access_grant,
|
155
|
-
default_attributes.merge(resource_owner_id: 90)
|
153
|
+
default_attributes.merge(resource_owner_id: 90),
|
156
154
|
)
|
157
155
|
|
158
156
|
described_class.revoke_all_for application.id, resource_owner
|
@@ -212,7 +212,7 @@ module Doorkeeper
|
|
212
212
|
end
|
213
213
|
|
214
214
|
expect { FactoryBot.create :access_token }.to(
|
215
|
-
raise_error(Doorkeeper::Errors::UnableToGenerateToken)
|
215
|
+
raise_error(Doorkeeper::Errors::UnableToGenerateToken),
|
216
216
|
)
|
217
217
|
end
|
218
218
|
|
@@ -234,7 +234,7 @@ module Doorkeeper
|
|
234
234
|
end
|
235
235
|
|
236
236
|
expect { FactoryBot.create :access_token }.to(
|
237
|
-
raise_error(LoadError)
|
237
|
+
raise_error(LoadError),
|
238
238
|
)
|
239
239
|
end
|
240
240
|
|
@@ -245,7 +245,7 @@ module Doorkeeper
|
|
245
245
|
end
|
246
246
|
|
247
247
|
expect { FactoryBot.create :access_token }.to(
|
248
|
-
raise_error(Doorkeeper::Errors::TokenGeneratorNotFound, /NotReal/)
|
248
|
+
raise_error(Doorkeeper::Errors::TokenGeneratorNotFound, /NotReal/),
|
249
249
|
)
|
250
250
|
end
|
251
251
|
end
|
@@ -468,7 +468,7 @@ module Doorkeeper
|
|
468
468
|
it "matches application" do
|
469
469
|
access_token_for_different_app = FactoryBot.create(
|
470
470
|
:access_token,
|
471
|
-
default_attributes.merge(application: FactoryBot.create(:application))
|
471
|
+
default_attributes.merge(application: FactoryBot.create(:application)),
|
472
472
|
)
|
473
473
|
|
474
474
|
AccessToken.revoke_all_for application.id, resource_owner
|
@@ -479,7 +479,7 @@ module Doorkeeper
|
|
479
479
|
it "matches resource owner" do
|
480
480
|
access_token_for_different_owner = FactoryBot.create(
|
481
481
|
:access_token,
|
482
|
-
default_attributes.merge(resource_owner_id: 90)
|
482
|
+
default_attributes.merge(resource_owner_id: 90),
|
483
483
|
)
|
484
484
|
|
485
485
|
AccessToken.revoke_all_for application.id, resource_owner
|
@@ -561,7 +561,7 @@ module Doorkeeper
|
|
561
561
|
|
562
562
|
it "excludes tokens with scopes that are not present in server scopes" do
|
563
563
|
FactoryBot.create :access_token, default_attributes.merge(
|
564
|
-
application: application, scopes: "public read"
|
564
|
+
application: application, scopes: "public read",
|
565
565
|
)
|
566
566
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
567
567
|
expect(last_token).to be_nil
|
@@ -570,7 +570,7 @@ module Doorkeeper
|
|
570
570
|
it "excludes tokens with scopes that are not present in application scopes" do
|
571
571
|
application = FactoryBot.create :application, scopes: "private read"
|
572
572
|
FactoryBot.create :access_token, default_attributes.merge(
|
573
|
-
application: application
|
573
|
+
application: application,
|
574
574
|
)
|
575
575
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
576
576
|
expect(last_token).to be_nil
|
@@ -4,8 +4,8 @@ require "spec_helper"
|
|
4
4
|
require "bcrypt"
|
5
5
|
|
6
6
|
describe Doorkeeper::Application do
|
7
|
-
let(:require_owner) { Doorkeeper.
|
8
|
-
let(:unset_require_owner) { Doorkeeper.
|
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
9
|
let(:new_application) { FactoryBot.build(:application) }
|
10
10
|
|
11
11
|
let(:uid) { SecureRandom.hex(8) }
|
@@ -79,9 +79,11 @@ feature "Authorization endpoint" do
|
|
79
79
|
scenario "raises exception on forged requests" do
|
80
80
|
allowing_forgery_protection do
|
81
81
|
expect do
|
82
|
-
page.driver.post authorization_endpoint_url(
|
83
|
-
|
84
|
-
|
82
|
+
page.driver.post authorization_endpoint_url(
|
83
|
+
client_id: @client.uid,
|
84
|
+
redirect_uri: @client.redirect_uri,
|
85
|
+
response_type: "code",
|
86
|
+
)
|
85
87
|
end.to raise_error(ActionController::InvalidAuthenticityToken)
|
86
88
|
end
|
87
89
|
end
|
@@ -149,8 +149,10 @@ feature "Authorization Code Flow" do
|
|
149
149
|
click_on "Authorize"
|
150
150
|
|
151
151
|
authorization_code = Doorkeeper::AccessGrant.first.token
|
152
|
-
page.driver.post token_endpoint_url(
|
153
|
-
|
152
|
+
page.driver.post token_endpoint_url(
|
153
|
+
code: authorization_code, client_id: @client.uid,
|
154
|
+
redirect_uri: @client.redirect_uri,
|
155
|
+
)
|
154
156
|
|
155
157
|
expect(Doorkeeper::AccessToken.count).to be_zero
|
156
158
|
|
@@ -163,8 +165,10 @@ feature "Authorization Code Flow" do
|
|
163
165
|
click_on "Authorize"
|
164
166
|
|
165
167
|
authorization_code = Doorkeeper::AccessGrant.first.token
|
166
|
-
page.driver.post token_endpoint_url(
|
167
|
-
|
168
|
+
page.driver.post token_endpoint_url(
|
169
|
+
code: authorization_code, client_secret: @client.secret,
|
170
|
+
redirect_uri: @client.redirect_uri,
|
171
|
+
)
|
168
172
|
|
169
173
|
expect(Doorkeeper::AccessToken.count).to be_zero
|
170
174
|
|
@@ -195,7 +199,7 @@ feature "Authorization Code Flow" do
|
|
195
199
|
visit authorization_endpoint_url(
|
196
200
|
client: @client,
|
197
201
|
code_challenge: code_challenge,
|
198
|
-
code_challenge_method: "plain"
|
202
|
+
code_challenge_method: "plain",
|
199
203
|
)
|
200
204
|
click_on "Authorize"
|
201
205
|
|
@@ -219,7 +223,7 @@ feature "Authorization Code Flow" do
|
|
219
223
|
visit authorization_endpoint_url(
|
220
224
|
client: @client,
|
221
225
|
code_challenge: code_challenge,
|
222
|
-
code_challenge_method: "plain"
|
226
|
+
code_challenge_method: "plain",
|
223
227
|
)
|
224
228
|
click_on "Authorize"
|
225
229
|
|
@@ -236,9 +240,11 @@ feature "Authorization Code Flow" do
|
|
236
240
|
end
|
237
241
|
|
238
242
|
scenario "mobile app requests an access token with authorization code but without code_verifier" do
|
239
|
-
visit authorization_endpoint_url(
|
240
|
-
|
241
|
-
|
243
|
+
visit authorization_endpoint_url(
|
244
|
+
client: @client,
|
245
|
+
code_challenge: code_challenge,
|
246
|
+
code_challenge_method: "plain",
|
247
|
+
)
|
242
248
|
click_on "Authorize"
|
243
249
|
|
244
250
|
authorization_code = current_params["code"]
|
@@ -250,9 +256,11 @@ feature "Authorization Code Flow" do
|
|
250
256
|
end
|
251
257
|
|
252
258
|
scenario "mobile app requests an access token with authorization code with wrong code_verifier" do
|
253
|
-
visit authorization_endpoint_url(
|
254
|
-
|
255
|
-
|
259
|
+
visit authorization_endpoint_url(
|
260
|
+
client: @client,
|
261
|
+
code_challenge: code_challenge,
|
262
|
+
code_challenge_method: "plain",
|
263
|
+
)
|
256
264
|
click_on "Authorize"
|
257
265
|
|
258
266
|
authorization_code = current_params["code"]
|
@@ -272,7 +280,7 @@ feature "Authorization Code Flow" do
|
|
272
280
|
visit authorization_endpoint_url(
|
273
281
|
client: @client,
|
274
282
|
code_challenge: code_challenge,
|
275
|
-
code_challenge_method: "S256"
|
283
|
+
code_challenge_method: "S256",
|
276
284
|
)
|
277
285
|
click_on "Authorize"
|
278
286
|
|
@@ -285,7 +293,7 @@ feature "Authorization Code Flow" do
|
|
285
293
|
visit authorization_endpoint_url(
|
286
294
|
client: @client,
|
287
295
|
code_challenge: code_challenge,
|
288
|
-
code_challenge_method: "S256"
|
296
|
+
code_challenge_method: "S256",
|
289
297
|
)
|
290
298
|
click_on "Authorize"
|
291
299
|
|
@@ -305,13 +313,17 @@ feature "Authorization Code Flow" do
|
|
305
313
|
visit authorization_endpoint_url(
|
306
314
|
client: @client,
|
307
315
|
code_challenge: code_challenge,
|
308
|
-
code_challenge_method: "S256"
|
316
|
+
code_challenge_method: "S256",
|
309
317
|
)
|
310
318
|
click_on "Authorize"
|
311
319
|
|
312
320
|
authorization_code = current_params["code"]
|
313
|
-
page.driver.post token_endpoint_url(
|
314
|
-
|
321
|
+
page.driver.post token_endpoint_url(
|
322
|
+
code: authorization_code,
|
323
|
+
client_id: @client.uid,
|
324
|
+
redirect_uri: @client.redirect_uri,
|
325
|
+
code_verifier: code_verifier,
|
326
|
+
)
|
315
327
|
should_not_have_json "access_token"
|
316
328
|
should_have_json "error", "invalid_client"
|
317
329
|
should_have_json "error_description", translated_error_message(:invalid_client)
|
@@ -327,7 +339,7 @@ feature "Authorization Code Flow" do
|
|
327
339
|
code: authorization_code,
|
328
340
|
client_id: @client.uid,
|
329
341
|
redirect_uri: @client.redirect_uri,
|
330
|
-
code_verifier: code_verifier
|
342
|
+
code_verifier: code_verifier,
|
331
343
|
)
|
332
344
|
should_not_have_json "error"
|
333
345
|
|
@@ -340,7 +352,7 @@ feature "Authorization Code Flow" do
|
|
340
352
|
visit authorization_endpoint_url(
|
341
353
|
client: @client,
|
342
354
|
code_challenge: code_challenge,
|
343
|
-
code_challenge_method: "S256"
|
355
|
+
code_challenge_method: "S256",
|
344
356
|
)
|
345
357
|
click_on "Authorize"
|
346
358
|
|
@@ -356,7 +368,7 @@ feature "Authorization Code Flow" do
|
|
356
368
|
visit authorization_endpoint_url(
|
357
369
|
client: @client,
|
358
370
|
code_challenge: code_challenge,
|
359
|
-
code_challenge_method: "S256"
|
371
|
+
code_challenge_method: "S256",
|
360
372
|
)
|
361
373
|
click_on "Authorize"
|
362
374
|
|
@@ -372,7 +384,7 @@ feature "Authorization Code Flow" do
|
|
372
384
|
visit authorization_endpoint_url(
|
373
385
|
client: @client,
|
374
386
|
code_challenge: code_challenge,
|
375
|
-
code_challenge_method: "S256"
|
387
|
+
code_challenge_method: "S256",
|
376
388
|
)
|
377
389
|
click_on "Authorize"
|
378
390
|
|
@@ -381,7 +393,7 @@ feature "Authorization Code Flow" do
|
|
381
393
|
code: authorization_code,
|
382
394
|
client: @client,
|
383
395
|
code_verifier: code_challenge,
|
384
|
-
code_challenge_method: "plain"
|
396
|
+
code_challenge_method: "plain",
|
385
397
|
)
|
386
398
|
|
387
399
|
should_not_have_json "access_token"
|
@@ -70,7 +70,7 @@ describe "Client Credentials Request" do
|
|
70
70
|
before do
|
71
71
|
Doorkeeper.configuration.instance_variable_set(
|
72
72
|
:@allow_grant_flow_for_client,
|
73
|
-
->(_grant_flow, client) { client.name == "admin" }
|
73
|
+
->(_grant_flow, client) { client.name == "admin" },
|
74
74
|
)
|
75
75
|
end
|
76
76
|
|
@@ -35,7 +35,7 @@ describe "Resource Owner Password Credentials Flow" do
|
|
35
35
|
before do
|
36
36
|
Doorkeeper.configuration.instance_variable_set(
|
37
37
|
:@allow_grant_flow_for_client,
|
38
|
-
->(_grant_flow, client) { client.name == "admin" }
|
38
|
+
->(_grant_flow, client) { client.name == "admin" },
|
39
39
|
)
|
40
40
|
end
|
41
41
|
|
@@ -46,7 +46,7 @@ describe "Resource Owner Password Credentials Flow" do
|
|
46
46
|
post password_token_endpoint_url(
|
47
47
|
client_id: @client.uid,
|
48
48
|
client_secret: "foobar",
|
49
|
-
resource_owner: @resource_owner
|
49
|
+
resource_owner: @resource_owner,
|
50
50
|
)
|
51
51
|
end.not_to(change { Doorkeeper::AccessToken.count })
|
52
52
|
|
@@ -99,7 +99,7 @@ describe "Resource Owner Password Credentials Flow" do
|
|
99
99
|
post password_token_endpoint_url(
|
100
100
|
client_id: @client.uid,
|
101
101
|
client_secret: "foobar",
|
102
|
-
resource_owner: @resource_owner
|
102
|
+
resource_owner: @resource_owner,
|
103
103
|
)
|
104
104
|
end.not_to(change { Doorkeeper::AccessToken.count })
|
105
105
|
|
@@ -241,9 +241,11 @@ describe "Resource Owner Password Credentials Flow" do
|
|
241
241
|
|
242
242
|
context "with invalid scopes" do
|
243
243
|
subject do
|
244
|
-
post password_token_endpoint_url(
|
245
|
-
|
246
|
-
|
244
|
+
post password_token_endpoint_url(
|
245
|
+
client: @client,
|
246
|
+
resource_owner: @resource_owner,
|
247
|
+
scope: "random",
|
248
|
+
)
|
247
249
|
end
|
248
250
|
|
249
251
|
it "should not issue new token" do
|
@@ -263,9 +265,11 @@ describe "Resource Owner Password Credentials Flow" do
|
|
263
265
|
context "with invalid user credentials" do
|
264
266
|
it "should not issue new token with bad password" do
|
265
267
|
expect do
|
266
|
-
post password_token_endpoint_url(
|
267
|
-
|
268
|
-
|
268
|
+
post password_token_endpoint_url(
|
269
|
+
client: @client,
|
270
|
+
resource_owner_username: @resource_owner.name,
|
271
|
+
resource_owner_password: "wrongpassword",
|
272
|
+
)
|
269
273
|
end.to_not(change { Doorkeeper::AccessToken.count })
|
270
274
|
end
|
271
275
|
|
@@ -274,14 +278,30 @@ describe "Resource Owner Password Credentials Flow" do
|
|
274
278
|
post password_token_endpoint_url(client: @client)
|
275
279
|
end.to_not(change { Doorkeeper::AccessToken.count })
|
276
280
|
end
|
281
|
+
|
282
|
+
it "should not issue new token if resource_owner_from_credentials returned false or nil" do
|
283
|
+
config_is_set(:resource_owner_from_credentials) { false }
|
284
|
+
|
285
|
+
expect do
|
286
|
+
post password_token_endpoint_url(client: @client)
|
287
|
+
end.to_not(change { Doorkeeper::AccessToken.count })
|
288
|
+
|
289
|
+
config_is_set(:resource_owner_from_credentials) { nil }
|
290
|
+
|
291
|
+
expect do
|
292
|
+
post password_token_endpoint_url(client: @client)
|
293
|
+
end.to_not(change { Doorkeeper::AccessToken.count })
|
294
|
+
end
|
277
295
|
end
|
278
296
|
|
279
297
|
context "with invalid confidential client credentials" do
|
280
298
|
it "should not issue new token with bad client credentials" do
|
281
299
|
expect do
|
282
|
-
post password_token_endpoint_url(
|
283
|
-
|
284
|
-
|
300
|
+
post password_token_endpoint_url(
|
301
|
+
client_id: @client.uid,
|
302
|
+
client_secret: "bad_secret",
|
303
|
+
resource_owner: @resource_owner,
|
304
|
+
)
|
285
305
|
end.to_not(change { Doorkeeper::AccessToken.count })
|
286
306
|
end
|
287
307
|
end
|