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
|
@@ -5,7 +5,11 @@ require "spec_helper"
|
|
|
5
5
|
describe "Token endpoint" do
|
|
6
6
|
before do
|
|
7
7
|
client_exists
|
|
8
|
-
|
|
8
|
+
create_resource_owner
|
|
9
|
+
authorization_code_exists application: @client,
|
|
10
|
+
scopes: "public",
|
|
11
|
+
resource_owner_id: @resource_owner.id,
|
|
12
|
+
resource_owner_type: @resource_owner.class.name
|
|
9
13
|
end
|
|
10
14
|
|
|
11
15
|
it "respond with correct headers" do
|
|
@@ -50,7 +50,10 @@ end
|
|
|
50
50
|
describe "Authorization Code Flow Errors", "after authorization" do
|
|
51
51
|
before do
|
|
52
52
|
client_exists
|
|
53
|
-
|
|
53
|
+
create_resource_owner
|
|
54
|
+
authorization_code_exists application: @client,
|
|
55
|
+
resource_owner_id: @resource_owner.id,
|
|
56
|
+
resource_owner_type: @resource_owner.class.name
|
|
54
57
|
end
|
|
55
58
|
|
|
56
59
|
it "returns :invalid_grant error when posting an already revoked grant code" do
|
|
@@ -182,6 +182,7 @@ feature "Authorization Code Flow" do
|
|
|
182
182
|
access_token_exists application: @client,
|
|
183
183
|
expires_in: -100, # even expired token
|
|
184
184
|
resource_owner_id: @resource_owner.id,
|
|
185
|
+
resource_owner_type: @resource_owner.class.name,
|
|
185
186
|
scopes: "public write"
|
|
186
187
|
|
|
187
188
|
visit authorization_endpoint_url(client: @client, scope: "public write")
|
|
@@ -506,8 +507,12 @@ describe "Authorization Code Flow" do
|
|
|
506
507
|
end
|
|
507
508
|
|
|
508
509
|
context "issuing a refresh token" do
|
|
510
|
+
let(:resource_owner) { FactoryBot.create(:resource_owner) }
|
|
511
|
+
|
|
509
512
|
before do
|
|
510
|
-
authorization_code_exists application: @client
|
|
513
|
+
authorization_code_exists application: @client,
|
|
514
|
+
resource_owner_id: resource_owner.id,
|
|
515
|
+
resource_owner_type: resource_owner.class.name
|
|
511
516
|
end
|
|
512
517
|
|
|
513
518
|
it "second of simultaneous client requests get an error for revoked acccess token" do
|
|
@@ -159,6 +159,47 @@ describe "Client Credentials Request" do
|
|
|
159
159
|
end
|
|
160
160
|
end
|
|
161
161
|
|
|
162
|
+
context "when revoke_previous_client_credentials_token is true" do
|
|
163
|
+
before do
|
|
164
|
+
allow(Doorkeeper.config).to receive(:reuse_access_token) { false }
|
|
165
|
+
allow(Doorkeeper.config).to receive(:revoke_previous_client_credentials_token) { true }
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it "revokes the previous token" do
|
|
169
|
+
headers = authorization client.uid, client.secret
|
|
170
|
+
params = { grant_type: "client_credentials" }
|
|
171
|
+
|
|
172
|
+
post "/oauth/token", params: params, headers: headers
|
|
173
|
+
should_have_json "access_token", Doorkeeper::AccessToken.first.token
|
|
174
|
+
|
|
175
|
+
token = Doorkeeper::AccessToken.first
|
|
176
|
+
|
|
177
|
+
post "/oauth/token", params: params, headers: headers
|
|
178
|
+
should_have_json "access_token", Doorkeeper::AccessToken.last.token
|
|
179
|
+
|
|
180
|
+
expect(token.reload.revoked?).to be_truthy
|
|
181
|
+
expect(Doorkeeper::AccessToken.last.revoked?).to be_falsey
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
context "with a simultaneous request" do
|
|
185
|
+
let!(:access_token) { FactoryBot.create :access_token, resource_owner_id: nil }
|
|
186
|
+
|
|
187
|
+
before do
|
|
188
|
+
allow(Doorkeeper.config.access_token_model).to receive(:matching_token_for) { access_token }
|
|
189
|
+
allow(access_token).to receive(:revoked?).and_return(true)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it "returns an error" do
|
|
193
|
+
headers = authorization client.uid, client.secret
|
|
194
|
+
params = { grant_type: "client_credentials" }
|
|
195
|
+
|
|
196
|
+
post "/oauth/token", params: params, headers: headers
|
|
197
|
+
should_not_have_json "access_token"
|
|
198
|
+
should_have_json "error", "invalid_token_reuse"
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
162
203
|
def authorization(username, password)
|
|
163
204
|
credentials = ActionController::HttpAuthentication::Basic.encode_credentials username, password
|
|
164
205
|
{ "HTTP_AUTHORIZATION" => credentials }
|
|
@@ -12,9 +12,13 @@ describe "Refresh Token Flow" do
|
|
|
12
12
|
client_exists
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
+
let(:resource_owner) { FactoryBot.create(:resource_owner) }
|
|
16
|
+
|
|
15
17
|
context "issuing a refresh token" do
|
|
16
18
|
before do
|
|
17
|
-
authorization_code_exists application: @client
|
|
19
|
+
authorization_code_exists application: @client,
|
|
20
|
+
resource_owner_id: resource_owner.id,
|
|
21
|
+
resource_owner_type: resource_owner.class.name
|
|
18
22
|
end
|
|
19
23
|
|
|
20
24
|
it "client gets the refresh token and refreshes it" do
|
|
@@ -43,7 +47,8 @@ describe "Refresh Token Flow" do
|
|
|
43
47
|
@token = FactoryBot.create(
|
|
44
48
|
:access_token,
|
|
45
49
|
application: @client,
|
|
46
|
-
resource_owner_id:
|
|
50
|
+
resource_owner_id: resource_owner.id,
|
|
51
|
+
resource_owner_type: resource_owner.class.name,
|
|
47
52
|
use_refresh_token: true,
|
|
48
53
|
)
|
|
49
54
|
end
|
|
@@ -110,7 +115,8 @@ describe "Refresh Token Flow" do
|
|
|
110
115
|
FactoryBot.create(
|
|
111
116
|
:access_token,
|
|
112
117
|
application: @client,
|
|
113
|
-
resource_owner_id:
|
|
118
|
+
resource_owner_id: resource_owner.id,
|
|
119
|
+
resource_owner_type: resource_owner.class.name,
|
|
114
120
|
use_refresh_token: true,
|
|
115
121
|
)
|
|
116
122
|
end
|
|
@@ -119,7 +125,8 @@ describe "Refresh Token Flow" do
|
|
|
119
125
|
FactoryBot.create(
|
|
120
126
|
:access_token,
|
|
121
127
|
application: public_client,
|
|
122
|
-
resource_owner_id:
|
|
128
|
+
resource_owner_id: resource_owner.id,
|
|
129
|
+
resource_owner_type: resource_owner.class.name,
|
|
123
130
|
use_refresh_token: true,
|
|
124
131
|
)
|
|
125
132
|
end
|
|
@@ -185,14 +192,15 @@ describe "Refresh Token Flow" do
|
|
|
185
192
|
end
|
|
186
193
|
create_resource_owner
|
|
187
194
|
_another_token = post password_token_endpoint_url(
|
|
188
|
-
client: @client, resource_owner:
|
|
195
|
+
client: @client, resource_owner: resource_owner,
|
|
189
196
|
)
|
|
190
|
-
last_token.
|
|
197
|
+
last_token.update(created_at: 5.seconds.ago)
|
|
191
198
|
|
|
192
199
|
@token = FactoryBot.create(
|
|
193
200
|
:access_token,
|
|
194
201
|
application: @client,
|
|
195
|
-
resource_owner_id:
|
|
202
|
+
resource_owner_id: resource_owner.id,
|
|
203
|
+
resource_owner_type: resource_owner.class.name,
|
|
196
204
|
use_refresh_token: true,
|
|
197
205
|
)
|
|
198
206
|
@token.update_attribute :expires_in, -100
|
|
@@ -226,7 +234,7 @@ describe "Refresh Token Flow" do
|
|
|
226
234
|
|
|
227
235
|
def last_token
|
|
228
236
|
Doorkeeper::AccessToken.last_authorized_token_for(
|
|
229
|
-
@client.id,
|
|
237
|
+
@client.id, resource_owner,
|
|
230
238
|
)
|
|
231
239
|
end
|
|
232
240
|
end
|
|
@@ -7,151 +7,190 @@ describe "Revoke Token Flow" do
|
|
|
7
7
|
Doorkeeper.configure { orm DOORKEEPER_ORM }
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
let(:private_client_application) { FactoryBot.create :application }
|
|
11
|
+
let(:public_client_application) { FactoryBot.create :application, confidential: false }
|
|
12
|
+
let(:resource_owner) { User.create!(name: "John", password: "sekret") }
|
|
13
|
+
|
|
14
|
+
context "with authenticated, confidential OAuth 2.0 client/application" do
|
|
13
15
|
let(:access_token) do
|
|
14
16
|
FactoryBot.create(
|
|
15
17
|
:access_token,
|
|
16
|
-
application:
|
|
18
|
+
application: private_client_application,
|
|
17
19
|
resource_owner_id: resource_owner.id,
|
|
20
|
+
resource_owner_type: resource_owner.class.name,
|
|
18
21
|
use_refresh_token: true,
|
|
19
22
|
)
|
|
20
23
|
end
|
|
21
24
|
|
|
22
|
-
|
|
25
|
+
let(:headers) do
|
|
26
|
+
client_id = private_client_application.uid
|
|
27
|
+
client_secret = private_client_application.secret
|
|
28
|
+
credentials = Base64.encode64("#{client_id}:#{client_secret}")
|
|
29
|
+
{ "HTTP_AUTHORIZATION" => "Basic #{credentials}" }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should revoke the access token provided" do
|
|
33
|
+
post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
|
|
34
|
+
|
|
35
|
+
expect(response).to be_successful
|
|
36
|
+
expect(access_token.reload.revoked?).to be_truthy
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should revoke the refresh token provided" do
|
|
40
|
+
post revocation_token_endpoint_url, params: { token: access_token.refresh_token }, headers: headers
|
|
41
|
+
|
|
42
|
+
expect(response).to be_successful
|
|
43
|
+
expect(access_token.reload.revoked?).to be_truthy
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context "with invalid token to revoke" do
|
|
47
|
+
it "should not revoke any tokens and must respond with success" do
|
|
48
|
+
expect do
|
|
49
|
+
post revocation_token_endpoint_url,
|
|
50
|
+
params: { token: "I_AM_AN_INVALID_TOKEN" },
|
|
51
|
+
headers: headers
|
|
52
|
+
end.not_to(change { Doorkeeper::AccessToken.where(revoked_at: nil).count })
|
|
53
|
+
|
|
54
|
+
expect(response).to be_successful
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context "with bad credentials and a valid token" do
|
|
23
59
|
let(:headers) do
|
|
24
|
-
client_id =
|
|
25
|
-
|
|
26
|
-
credentials = Base64.encode64("#{client_id}:#{client_secret}")
|
|
60
|
+
client_id = private_client_application.uid
|
|
61
|
+
credentials = Base64.encode64("#{client_id}:poop")
|
|
27
62
|
{ "HTTP_AUTHORIZATION" => "Basic #{credentials}" }
|
|
28
63
|
end
|
|
29
64
|
|
|
30
|
-
it "should revoke
|
|
65
|
+
it "should not revoke any tokens and respond with forbidden" do
|
|
31
66
|
post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
|
|
32
67
|
|
|
33
|
-
expect(response).to
|
|
34
|
-
expect(
|
|
68
|
+
expect(response).to be_forbidden
|
|
69
|
+
expect(response.body).to include("unauthorized_client")
|
|
70
|
+
expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
|
|
71
|
+
expect(access_token.reload.revoked?).to be_falsey
|
|
35
72
|
end
|
|
73
|
+
end
|
|
36
74
|
|
|
37
|
-
|
|
38
|
-
|
|
75
|
+
context "with no credentials and a valid token" do
|
|
76
|
+
it "should not revoke any tokens and respond with forbidden" do
|
|
77
|
+
post revocation_token_endpoint_url, params: { token: access_token.token }
|
|
39
78
|
|
|
40
|
-
expect(response).to
|
|
41
|
-
expect(
|
|
79
|
+
expect(response).to be_forbidden
|
|
80
|
+
expect(response.body).to include("unauthorized_client")
|
|
81
|
+
expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
|
|
82
|
+
expect(access_token.reload.revoked?).to be_falsey
|
|
42
83
|
end
|
|
84
|
+
end
|
|
43
85
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
expect(response).to be_forbidden
|
|
53
|
-
end
|
|
86
|
+
context "with valid token for another client application" do
|
|
87
|
+
let(:other_client_application) { FactoryBot.create :application }
|
|
88
|
+
let(:headers) do
|
|
89
|
+
client_id = other_client_application.uid
|
|
90
|
+
client_secret = other_client_application.secret
|
|
91
|
+
credentials = Base64.encode64("#{client_id}:#{client_secret}")
|
|
92
|
+
{ "HTTP_AUTHORIZATION" => "Basic #{credentials}" }
|
|
54
93
|
end
|
|
55
94
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
|
|
64
|
-
|
|
65
|
-
expect(response).to be_forbidden
|
|
66
|
-
expect(response.body).to include("unauthorized_client")
|
|
67
|
-
expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
|
|
68
|
-
expect(access_token.reload.revoked?).to be_falsey
|
|
69
|
-
end
|
|
95
|
+
it "should not revoke the token as it's unauthorized" do
|
|
96
|
+
post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
|
|
97
|
+
|
|
98
|
+
expect(response).to be_forbidden
|
|
99
|
+
expect(response.body).to include("unauthorized_client")
|
|
100
|
+
expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
|
|
101
|
+
expect(access_token.reload.revoked?).to be_falsey
|
|
70
102
|
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
context "with authenticated public OAuth 2.0 client/application" do
|
|
107
|
+
let(:access_token) do
|
|
108
|
+
FactoryBot.create(
|
|
109
|
+
:access_token,
|
|
110
|
+
application: nil,
|
|
111
|
+
resource_owner_id: resource_owner.id,
|
|
112
|
+
resource_owner_type: resource_owner.class.name,
|
|
113
|
+
use_refresh_token: true,
|
|
114
|
+
)
|
|
115
|
+
end
|
|
71
116
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
117
|
+
it "should revoke the access token provided" do
|
|
118
|
+
post revocation_token_endpoint_url,
|
|
119
|
+
params: { client_id: public_client_application.uid, token: access_token.token },
|
|
120
|
+
headers: headers
|
|
75
121
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
expect(access_token.reload.revoked?).to be_falsey
|
|
80
|
-
end
|
|
81
|
-
end
|
|
122
|
+
expect(response).to be_successful
|
|
123
|
+
expect(access_token.reload.revoked?).to be_truthy
|
|
124
|
+
end
|
|
82
125
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
it "should not revoke the token as its unauthorized" do
|
|
93
|
-
post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
|
|
94
|
-
|
|
95
|
-
expect(response).to be_forbidden
|
|
96
|
-
expect(response.body).to include("unauthorized_client")
|
|
97
|
-
expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
|
|
98
|
-
expect(access_token.reload.revoked?).to be_falsey
|
|
99
|
-
end
|
|
100
|
-
end
|
|
126
|
+
it "should revoke the refresh token provided" do
|
|
127
|
+
post revocation_token_endpoint_url,
|
|
128
|
+
params: { client_id: public_client_application.uid, token: access_token.refresh_token },
|
|
129
|
+
headers: headers
|
|
130
|
+
|
|
131
|
+
expect(response).to be_successful
|
|
132
|
+
expect(access_token.reload.revoked?).to be_truthy
|
|
101
133
|
end
|
|
102
134
|
|
|
103
|
-
|
|
135
|
+
it "should response with success even for invalid token" do
|
|
136
|
+
post revocation_token_endpoint_url,
|
|
137
|
+
params: { client_id: public_client_application.uid, token: "dont_exist" },
|
|
138
|
+
headers: headers
|
|
139
|
+
|
|
140
|
+
expect(response).to be_successful
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
context "with a valid token issued for a confidential client" do
|
|
104
144
|
let(:access_token) do
|
|
105
145
|
FactoryBot.create(
|
|
106
146
|
:access_token,
|
|
107
|
-
application:
|
|
147
|
+
application: private_client_application,
|
|
108
148
|
resource_owner_id: resource_owner.id,
|
|
149
|
+
resource_owner_type: resource_owner.class.name,
|
|
109
150
|
use_refresh_token: true,
|
|
110
151
|
)
|
|
111
152
|
end
|
|
112
153
|
|
|
113
|
-
it "should revoke the access token provided" do
|
|
114
|
-
post revocation_token_endpoint_url,
|
|
154
|
+
it "should not revoke the access token provided" do
|
|
155
|
+
post revocation_token_endpoint_url,
|
|
156
|
+
params: { client_id: public_client_application.uid, token: access_token.token }
|
|
115
157
|
|
|
116
|
-
expect(response).to
|
|
117
|
-
expect(
|
|
158
|
+
expect(response).to be_forbidden
|
|
159
|
+
expect(response.body).to include("unauthorized_client")
|
|
160
|
+
expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
|
|
161
|
+
expect(access_token.reload.revoked?).to be_falsey
|
|
118
162
|
end
|
|
119
163
|
|
|
120
|
-
it "should revoke the refresh token provided" do
|
|
121
|
-
post revocation_token_endpoint_url,
|
|
164
|
+
it "should not revoke the refresh token provided" do
|
|
165
|
+
post revocation_token_endpoint_url,
|
|
166
|
+
params: { client_id: public_client_application.uid, token: access_token.token }
|
|
122
167
|
|
|
123
|
-
expect(response).to
|
|
124
|
-
expect(
|
|
168
|
+
expect(response).to be_forbidden
|
|
169
|
+
expect(response.body).to include("unauthorized_client")
|
|
170
|
+
expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
|
|
171
|
+
expect(access_token.reload.revoked?).to be_falsey
|
|
125
172
|
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
126
175
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
it "should not revoke the refresh token provided" do
|
|
147
|
-
post revocation_token_endpoint_url, params: { token: access_token.token }
|
|
148
|
-
|
|
149
|
-
expect(response).to be_forbidden
|
|
150
|
-
expect(response.body).to include("unauthorized_client")
|
|
151
|
-
expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
|
|
152
|
-
expect(access_token.reload.revoked?).to be_falsey
|
|
153
|
-
end
|
|
154
|
-
end
|
|
176
|
+
context "without client authentication" do
|
|
177
|
+
let(:access_token) do
|
|
178
|
+
FactoryBot.create(
|
|
179
|
+
:access_token,
|
|
180
|
+
application: nil,
|
|
181
|
+
resource_owner_id: resource_owner.id,
|
|
182
|
+
resource_owner_type: resource_owner.class.name,
|
|
183
|
+
use_refresh_token: true,
|
|
184
|
+
)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
it "shouldn't remove the token and must response with an error" do
|
|
188
|
+
post revocation_token_endpoint_url,
|
|
189
|
+
params: { token: access_token.token },
|
|
190
|
+
headers: headers
|
|
191
|
+
|
|
192
|
+
expect(response).not_to be_successful
|
|
193
|
+
expect(access_token.reload.revoked?).to be_falsey
|
|
155
194
|
end
|
|
156
195
|
end
|
|
157
196
|
end
|
|
@@ -3,19 +3,19 @@
|
|
|
3
3
|
module AuthorizationRequestHelper
|
|
4
4
|
def resource_owner_is_authenticated(resource_owner = nil)
|
|
5
5
|
resource_owner ||= User.create!(name: "Joe", password: "sekret")
|
|
6
|
-
Doorkeeper.
|
|
6
|
+
Doorkeeper.config.instance_variable_set(:@authenticate_resource_owner, proc { resource_owner })
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
def resource_owner_is_not_authenticated
|
|
10
|
-
Doorkeeper.
|
|
10
|
+
Doorkeeper.config.instance_variable_set(:@authenticate_resource_owner, proc { redirect_to("/sign_in") })
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def default_scopes_exist(*scopes)
|
|
14
|
-
Doorkeeper.
|
|
14
|
+
Doorkeeper.config.instance_variable_set(:@default_scopes, Doorkeeper::OAuth::Scopes.from_array(scopes))
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def optional_scopes_exist(*scopes)
|
|
18
|
-
Doorkeeper.
|
|
18
|
+
Doorkeeper.config.instance_variable_set(:@optional_scopes, Doorkeeper::OAuth::Scopes.from_array(scopes))
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def client_should_be_authorized(client)
|
|
@@ -4,7 +4,7 @@ module ConfigHelper
|
|
|
4
4
|
def config_is_set(setting, value = nil, &block)
|
|
5
5
|
setting_ivar = "@#{setting}"
|
|
6
6
|
value = block_given? ? block : value
|
|
7
|
-
Doorkeeper.
|
|
7
|
+
Doorkeeper.config.instance_variable_set(setting_ivar, value)
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
|
|
@@ -40,13 +40,13 @@ end
|
|
|
40
40
|
shared_context "authenticated resource owner" do
|
|
41
41
|
before do
|
|
42
42
|
user = double(:resource, id: 1)
|
|
43
|
-
allow(Doorkeeper.
|
|
43
|
+
allow(Doorkeeper.config).to receive(:authenticate_resource_owner) { proc { user } }
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
shared_context "not authenticated resource owner" do
|
|
48
48
|
before do
|
|
49
|
-
allow(Doorkeeper.
|
|
49
|
+
allow(Doorkeeper.config).to receive(:authenticate_resource_owner) { proc { redirect_to "/" } }
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -31,20 +31,22 @@ end
|
|
|
31
31
|
|
|
32
32
|
shared_examples "a unique token" do
|
|
33
33
|
describe :token do
|
|
34
|
+
let(:owner) { FactoryBot.create(:resource_owner) }
|
|
35
|
+
|
|
34
36
|
it "is generated before validation" do
|
|
35
37
|
expect { subject.valid? }.to change { subject.token }.from(nil)
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
it "is not valid if token exists" do
|
|
39
|
-
token1 = FactoryBot.create factory_name
|
|
40
|
-
token2 = FactoryBot.create factory_name
|
|
41
|
+
token1 = FactoryBot.create factory_name, resource_owner_id: owner.id, resource_owner_type: owner.class.name
|
|
42
|
+
token2 = FactoryBot.create factory_name, resource_owner_id: owner.id, resource_owner_type: owner.class.name
|
|
41
43
|
token2.token = token1.token
|
|
42
44
|
expect(token2).not_to be_valid
|
|
43
45
|
end
|
|
44
46
|
|
|
45
47
|
it "expects database to throw an error when tokens are the same" do
|
|
46
|
-
token1 = FactoryBot.create factory_name
|
|
47
|
-
token2 = FactoryBot.create factory_name
|
|
48
|
+
token1 = FactoryBot.create factory_name, resource_owner_id: owner.id, resource_owner_type: owner.class.name
|
|
49
|
+
token2 = FactoryBot.create factory_name, resource_owner_id: owner.id, resource_owner_type: owner.class.name
|
|
48
50
|
token2.token = token1.token
|
|
49
51
|
expect do
|
|
50
52
|
token2.save!(validate: false)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: doorkeeper
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.4.0.rc1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Felipe Elias Philipp
|
|
@@ -11,7 +11,7 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date: 2020-
|
|
14
|
+
date: 2020-04-08 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: railties
|
|
@@ -221,6 +221,7 @@ files:
|
|
|
221
221
|
- gemfiles/rails_master.gemfile
|
|
222
222
|
- lib/doorkeeper.rb
|
|
223
223
|
- lib/doorkeeper/config.rb
|
|
224
|
+
- lib/doorkeeper/config/abstract_builder.rb
|
|
224
225
|
- lib/doorkeeper/config/option.rb
|
|
225
226
|
- lib/doorkeeper/engine.rb
|
|
226
227
|
- lib/doorkeeper/errors.rb
|
|
@@ -234,6 +235,7 @@ files:
|
|
|
234
235
|
- lib/doorkeeper/models/concerns/expirable.rb
|
|
235
236
|
- lib/doorkeeper/models/concerns/orderable.rb
|
|
236
237
|
- lib/doorkeeper/models/concerns/ownership.rb
|
|
238
|
+
- lib/doorkeeper/models/concerns/resource_ownerable.rb
|
|
237
239
|
- lib/doorkeeper/models/concerns/reusable.rb
|
|
238
240
|
- lib/doorkeeper/models/concerns/revocable.rb
|
|
239
241
|
- lib/doorkeeper/models/concerns/scopes.rb
|
|
@@ -260,6 +262,7 @@ files:
|
|
|
260
262
|
- lib/doorkeeper/oauth/helpers/scope_checker.rb
|
|
261
263
|
- lib/doorkeeper/oauth/helpers/unique_token.rb
|
|
262
264
|
- lib/doorkeeper/oauth/helpers/uri_checker.rb
|
|
265
|
+
- lib/doorkeeper/oauth/hooks/context.rb
|
|
263
266
|
- lib/doorkeeper/oauth/invalid_request_response.rb
|
|
264
267
|
- lib/doorkeeper/oauth/invalid_token_response.rb
|
|
265
268
|
- lib/doorkeeper/oauth/nonstandard.rb
|
|
@@ -282,8 +285,10 @@ files:
|
|
|
282
285
|
- lib/doorkeeper/orm/active_record/stale_records_cleaner.rb
|
|
283
286
|
- lib/doorkeeper/rails/helpers.rb
|
|
284
287
|
- lib/doorkeeper/rails/routes.rb
|
|
288
|
+
- lib/doorkeeper/rails/routes/abstract_router.rb
|
|
285
289
|
- lib/doorkeeper/rails/routes/mapper.rb
|
|
286
290
|
- lib/doorkeeper/rails/routes/mapping.rb
|
|
291
|
+
- lib/doorkeeper/rails/routes/registry.rb
|
|
287
292
|
- lib/doorkeeper/rake.rb
|
|
288
293
|
- lib/doorkeeper/rake/db.rake
|
|
289
294
|
- lib/doorkeeper/rake/setup.rake
|
|
@@ -305,6 +310,7 @@ files:
|
|
|
305
310
|
- lib/doorkeeper/version.rb
|
|
306
311
|
- lib/generators/doorkeeper/application_owner_generator.rb
|
|
307
312
|
- lib/generators/doorkeeper/confidential_applications_generator.rb
|
|
313
|
+
- lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb
|
|
308
314
|
- lib/generators/doorkeeper/install_generator.rb
|
|
309
315
|
- lib/generators/doorkeeper/migration_generator.rb
|
|
310
316
|
- lib/generators/doorkeeper/pkce_generator.rb
|
|
@@ -314,6 +320,7 @@ files:
|
|
|
314
320
|
- lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb
|
|
315
321
|
- lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb
|
|
316
322
|
- lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb
|
|
323
|
+
- lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb
|
|
317
324
|
- lib/generators/doorkeeper/templates/initializer.rb
|
|
318
325
|
- lib/generators/doorkeeper/templates/migration.rb.erb
|
|
319
326
|
- lib/generators/doorkeeper/views_generator.rb
|
|
@@ -366,6 +373,7 @@ files:
|
|
|
366
373
|
- spec/factories.rb
|
|
367
374
|
- spec/generators/application_owner_generator_spec.rb
|
|
368
375
|
- spec/generators/confidential_applications_generator_spec.rb
|
|
376
|
+
- spec/generators/enable_polymorphic_resource_owner_generator_spec.rb
|
|
369
377
|
- spec/generators/install_generator_spec.rb
|
|
370
378
|
- spec/generators/migration_generator_spec.rb
|
|
371
379
|
- spec/generators/pkce_generator_spec.rb
|
|
@@ -409,6 +417,7 @@ files:
|
|
|
409
417
|
- spec/lib/oauth/token_request_spec.rb
|
|
410
418
|
- spec/lib/oauth/token_response_spec.rb
|
|
411
419
|
- spec/lib/oauth/token_spec.rb
|
|
420
|
+
- spec/lib/option_spec.rb
|
|
412
421
|
- spec/lib/request/strategy_spec.rb
|
|
413
422
|
- spec/lib/secret_storing/base_spec.rb
|
|
414
423
|
- spec/lib/secret_storing/bcrypt_spec.rb
|
|
@@ -474,9 +483,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
474
483
|
version: '2.4'
|
|
475
484
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
476
485
|
requirements:
|
|
477
|
-
- - "
|
|
486
|
+
- - ">"
|
|
478
487
|
- !ruby/object:Gem::Version
|
|
479
|
-
version:
|
|
488
|
+
version: 1.3.1
|
|
480
489
|
requirements: []
|
|
481
490
|
rubygems_version: 3.0.2
|
|
482
491
|
signing_key:
|
|
@@ -532,6 +541,7 @@ test_files:
|
|
|
532
541
|
- spec/factories.rb
|
|
533
542
|
- spec/generators/application_owner_generator_spec.rb
|
|
534
543
|
- spec/generators/confidential_applications_generator_spec.rb
|
|
544
|
+
- spec/generators/enable_polymorphic_resource_owner_generator_spec.rb
|
|
535
545
|
- spec/generators/install_generator_spec.rb
|
|
536
546
|
- spec/generators/migration_generator_spec.rb
|
|
537
547
|
- spec/generators/pkce_generator_spec.rb
|
|
@@ -575,6 +585,7 @@ test_files:
|
|
|
575
585
|
- spec/lib/oauth/token_request_spec.rb
|
|
576
586
|
- spec/lib/oauth/token_response_spec.rb
|
|
577
587
|
- spec/lib/oauth/token_spec.rb
|
|
588
|
+
- spec/lib/option_spec.rb
|
|
578
589
|
- spec/lib/request/strategy_spec.rb
|
|
579
590
|
- spec/lib/secret_storing/base_spec.rb
|
|
580
591
|
- spec/lib/secret_storing/bcrypt_spec.rb
|