doorkeeper 5.1.0 → 5.3.0
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 +3 -3
- data/CHANGELOG.md +881 -0
- data/CONTRIBUTING.md +11 -9
- data/Dangerfile +2 -2
- data/Dockerfile +29 -0
- data/Gemfile +4 -3
- data/NEWS.md +1 -814
- data/README.md +11 -3
- data/RELEASING.md +6 -5
- data/app/controllers/doorkeeper/application_controller.rb +2 -2
- data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
- data/app/controllers/doorkeeper/applications_controller.rb +1 -0
- data/app/controllers/doorkeeper/authorizations_controller.rb +16 -9
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +32 -9
- data/app/views/doorkeeper/applications/_form.html.erb +0 -6
- data/app/views/doorkeeper/applications/show.html.erb +1 -1
- data/config/locales/en.yml +8 -2
- data/doorkeeper.gemspec +9 -1
- data/gemfiles/rails_5_0.gemfile +3 -2
- data/gemfiles/rails_5_1.gemfile +3 -2
- data/gemfiles/rails_5_2.gemfile +3 -2
- data/gemfiles/rails_6_0.gemfile +4 -3
- data/gemfiles/rails_master.gemfile +3 -2
- data/lib/doorkeeper/config/option.rb +13 -7
- data/lib/doorkeeper/config.rb +157 -42
- data/lib/doorkeeper/errors.rb +13 -18
- data/lib/doorkeeper/grape/helpers.rb +6 -2
- data/lib/doorkeeper/helpers/controller.rb +28 -7
- data/lib/doorkeeper/models/access_grant_mixin.rb +7 -6
- data/lib/doorkeeper/models/access_token_mixin.rb +99 -20
- 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 +12 -14
- data/lib/doorkeeper/oauth/authorization/token.rb +10 -7
- data/lib/doorkeeper/oauth/authorization_code_request.rb +31 -15
- data/lib/doorkeeper/oauth/base_request.rb +10 -4
- data/lib/doorkeeper/oauth/client.rb +7 -8
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +23 -2
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +7 -7
- data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +10 -2
- data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
- data/lib/doorkeeper/oauth/code_request.rb +5 -11
- data/lib/doorkeeper/oauth/code_response.rb +4 -4
- data/lib/doorkeeper/oauth/error.rb +1 -1
- data/lib/doorkeeper/oauth/error_response.rb +6 -6
- 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 +19 -5
- data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
- data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -2
- data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +9 -4
- data/lib/doorkeeper/oauth/pre_authorization.rb +76 -38
- data/lib/doorkeeper/oauth/refresh_token_request.rb +17 -14
- data/lib/doorkeeper/oauth/token.rb +2 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +26 -16
- data/lib/doorkeeper/oauth/token_request.rb +4 -18
- 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 +5 -83
- 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 +61 -0
- data/lib/doorkeeper/orm/active_record.rb +21 -6
- 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 +5 -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 +7 -12
- data/lib/doorkeeper/server.rb +3 -7
- data/lib/doorkeeper/stale_records_cleaner.rb +6 -2
- data/lib/doorkeeper/version.rb +1 -1
- data/lib/doorkeeper.rb +6 -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 +7 -7
- data/lib/generators/doorkeeper/templates/initializer.rb +149 -33
- data/lib/generators/doorkeeper/templates/migration.rb.erb +4 -1
- data/spec/controllers/application_metal_controller_spec.rb +1 -1
- data/spec/controllers/applications_controller_spec.rb +95 -1
- data/spec/controllers/authorizations_controller_spec.rb +156 -75
- data/spec/controllers/protected_resources_controller_spec.rb +28 -20
- data/spec/controllers/token_info_controller_spec.rb +1 -1
- data/spec/controllers/tokens_controller_spec.rb +206 -38
- data/spec/dummy/config/application.rb +3 -1
- data/spec/dummy/config/initializers/doorkeeper.rb +54 -9
- 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 +104 -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 +129 -115
- data/spec/lib/oauth/base_request_spec.rb +154 -135
- 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 +43 -3
- 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 -35
- 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/helpers/uri_checker_spec.rb +17 -2
- data/spec/lib/oauth/invalid_request_response_spec.rb +73 -0
- 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 +161 -153
- data/spec/lib/oauth/refresh_token_request_spec.rb +138 -138
- data/spec/lib/oauth/scopes_spec.rb +104 -106
- data/spec/lib/oauth/token_request_spec.rb +117 -110
- data/spec/lib/oauth/token_response_spec.rb +71 -73
- data/spec/lib/oauth/token_spec.rb +121 -123
- data/spec/lib/server_spec.rb +0 -12
- data/spec/models/doorkeeper/access_grant_spec.rb +21 -4
- data/spec/models/doorkeeper/access_token_spec.rb +42 -11
- data/spec/models/doorkeeper/application_spec.rb +114 -77
- data/spec/requests/applications/applications_request_spec.rb +1 -1
- data/spec/requests/endpoints/authorization_spec.rb +26 -8
- data/spec/requests/endpoints/token_spec.rb +1 -1
- data/spec/requests/flows/authorization_code_errors_spec.rb +1 -0
- data/spec/requests/flows/authorization_code_spec.rb +123 -45
- data/spec/requests/flows/client_credentials_spec.rb +38 -0
- data/spec/requests/flows/implicit_grant_errors_spec.rb +22 -10
- data/spec/requests/flows/implicit_grant_spec.rb +9 -8
- data/spec/requests/flows/password_spec.rb +67 -10
- data/spec/requests/flows/refresh_token_spec.rb +20 -20
- data/spec/requests/flows/revoke_token_spec.rb +37 -23
- data/spec/spec_helper.rb +1 -4
- data/spec/support/doorkeeper_rspec.rb +1 -1
- data/spec/support/helpers/request_spec_helper.rb +14 -2
- data/spec/support/shared/controllers_shared_context.rb +33 -23
- data/spec/validators/redirect_uri_validator_spec.rb +41 -16
- metadata +19 -16
- data/.coveralls.yml +0 -1
- data/.github/ISSUE_TEMPLATE.md +0 -25
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
- data/.gitignore +0 -20
- data/.gitlab-ci.yml +0 -16
- data/.hound.yml +0 -3
- data/.rspec +0 -1
- data/.rubocop.yml +0 -50
- data/.travis.yml +0 -35
- data/app/validators/redirect_uri_validator.rb +0 -50
- data/spec/support/http_method_shim.rb +0 -29
|
@@ -44,17 +44,17 @@ describe "Refresh Token Flow" do
|
|
|
44
44
|
:access_token,
|
|
45
45
|
application: @client,
|
|
46
46
|
resource_owner_id: 1,
|
|
47
|
-
use_refresh_token: true
|
|
47
|
+
use_refresh_token: true,
|
|
48
48
|
)
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
context "refresh_token revoked on use" do
|
|
52
52
|
it "client request a token with refresh token" do
|
|
53
53
|
post refresh_token_endpoint_url(
|
|
54
|
-
client: @client, refresh_token: @token.refresh_token
|
|
54
|
+
client: @client, refresh_token: @token.refresh_token,
|
|
55
55
|
)
|
|
56
56
|
should_have_json(
|
|
57
|
-
"refresh_token", Doorkeeper::AccessToken.last.refresh_token
|
|
57
|
+
"refresh_token", Doorkeeper::AccessToken.last.refresh_token,
|
|
58
58
|
)
|
|
59
59
|
expect(@token.reload).not_to be_revoked
|
|
60
60
|
end
|
|
@@ -62,10 +62,10 @@ describe "Refresh Token Flow" do
|
|
|
62
62
|
it "client request a token with expired access token" do
|
|
63
63
|
@token.update_attribute :expires_in, -100
|
|
64
64
|
post refresh_token_endpoint_url(
|
|
65
|
-
client: @client, refresh_token: @token.refresh_token
|
|
65
|
+
client: @client, refresh_token: @token.refresh_token,
|
|
66
66
|
)
|
|
67
67
|
should_have_json(
|
|
68
|
-
"refresh_token", Doorkeeper::AccessToken.last.refresh_token
|
|
68
|
+
"refresh_token", Doorkeeper::AccessToken.last.refresh_token,
|
|
69
69
|
)
|
|
70
70
|
expect(@token.reload).not_to be_revoked
|
|
71
71
|
end
|
|
@@ -78,10 +78,10 @@ describe "Refresh Token Flow" do
|
|
|
78
78
|
|
|
79
79
|
it "client request a token with refresh token" do
|
|
80
80
|
post refresh_token_endpoint_url(
|
|
81
|
-
client: @client, refresh_token: @token.refresh_token
|
|
81
|
+
client: @client, refresh_token: @token.refresh_token,
|
|
82
82
|
)
|
|
83
83
|
should_have_json(
|
|
84
|
-
"refresh_token", Doorkeeper::AccessToken.last.refresh_token
|
|
84
|
+
"refresh_token", Doorkeeper::AccessToken.last.refresh_token,
|
|
85
85
|
)
|
|
86
86
|
expect(@token.reload).to be_revoked
|
|
87
87
|
end
|
|
@@ -89,10 +89,10 @@ describe "Refresh Token Flow" do
|
|
|
89
89
|
it "client request a token with expired access token" do
|
|
90
90
|
@token.update_attribute :expires_in, -100
|
|
91
91
|
post refresh_token_endpoint_url(
|
|
92
|
-
client: @client, refresh_token: @token.refresh_token
|
|
92
|
+
client: @client, refresh_token: @token.refresh_token,
|
|
93
93
|
)
|
|
94
94
|
should_have_json(
|
|
95
|
-
"refresh_token", Doorkeeper::AccessToken.last.refresh_token
|
|
95
|
+
"refresh_token", Doorkeeper::AccessToken.last.refresh_token,
|
|
96
96
|
)
|
|
97
97
|
expect(@token.reload).to be_revoked
|
|
98
98
|
end
|
|
@@ -102,7 +102,7 @@ describe "Refresh Token Flow" do
|
|
|
102
102
|
let(:public_client) do
|
|
103
103
|
FactoryBot.create(
|
|
104
104
|
:application,
|
|
105
|
-
confidential: false
|
|
105
|
+
confidential: false,
|
|
106
106
|
)
|
|
107
107
|
end
|
|
108
108
|
|
|
@@ -111,7 +111,7 @@ describe "Refresh Token Flow" do
|
|
|
111
111
|
:access_token,
|
|
112
112
|
application: @client,
|
|
113
113
|
resource_owner_id: 1,
|
|
114
|
-
use_refresh_token: true
|
|
114
|
+
use_refresh_token: true,
|
|
115
115
|
)
|
|
116
116
|
end
|
|
117
117
|
|
|
@@ -120,14 +120,14 @@ describe "Refresh Token Flow" do
|
|
|
120
120
|
:access_token,
|
|
121
121
|
application: public_client,
|
|
122
122
|
resource_owner_id: 1,
|
|
123
|
-
use_refresh_token: true
|
|
123
|
+
use_refresh_token: true,
|
|
124
124
|
)
|
|
125
125
|
end
|
|
126
126
|
|
|
127
127
|
it "issues a new token without client_secret when refresh token was issued to a public client" do
|
|
128
128
|
post refresh_token_endpoint_url(
|
|
129
129
|
client_id: public_client.uid,
|
|
130
|
-
refresh_token: token_for_public_client.refresh_token
|
|
130
|
+
refresh_token: token_for_public_client.refresh_token,
|
|
131
131
|
)
|
|
132
132
|
|
|
133
133
|
new_token = Doorkeeper::AccessToken.last
|
|
@@ -146,7 +146,7 @@ describe "Refresh Token Flow" do
|
|
|
146
146
|
post refresh_token_endpoint_url(
|
|
147
147
|
client_id: "1",
|
|
148
148
|
client_secret: "1",
|
|
149
|
-
refresh_token: token_for_private_client.refresh_token
|
|
149
|
+
refresh_token: token_for_private_client.refresh_token,
|
|
150
150
|
)
|
|
151
151
|
|
|
152
152
|
should_not_have_json "refresh_token"
|
|
@@ -172,7 +172,7 @@ describe "Refresh Token Flow" do
|
|
|
172
172
|
post refresh_token_endpoint_url(client: @client, refresh_token: @token.refresh_token)
|
|
173
173
|
|
|
174
174
|
should_not_have_json "refresh_token"
|
|
175
|
-
should_have_json "error", "
|
|
175
|
+
should_have_json "error", "invalid_grant"
|
|
176
176
|
end
|
|
177
177
|
end
|
|
178
178
|
|
|
@@ -185,7 +185,7 @@ describe "Refresh Token Flow" do
|
|
|
185
185
|
end
|
|
186
186
|
create_resource_owner
|
|
187
187
|
_another_token = post password_token_endpoint_url(
|
|
188
|
-
client: @client, resource_owner: @resource_owner
|
|
188
|
+
client: @client, resource_owner: @resource_owner,
|
|
189
189
|
)
|
|
190
190
|
last_token.update_attribute :created_at, 5.seconds.ago
|
|
191
191
|
|
|
@@ -193,7 +193,7 @@ describe "Refresh Token Flow" do
|
|
|
193
193
|
:access_token,
|
|
194
194
|
application: @client,
|
|
195
195
|
resource_owner_id: @resource_owner.id,
|
|
196
|
-
use_refresh_token: true
|
|
196
|
+
use_refresh_token: true,
|
|
197
197
|
)
|
|
198
198
|
@token.update_attribute :expires_in, -100
|
|
199
199
|
end
|
|
@@ -201,7 +201,7 @@ describe "Refresh Token Flow" do
|
|
|
201
201
|
context "refresh_token revoked on use" do
|
|
202
202
|
it "client request a token after creating another token with the same user" do
|
|
203
203
|
post refresh_token_endpoint_url(
|
|
204
|
-
client: @client, refresh_token: @token.refresh_token
|
|
204
|
+
client: @client, refresh_token: @token.refresh_token,
|
|
205
205
|
)
|
|
206
206
|
|
|
207
207
|
should_have_json "refresh_token", last_token.refresh_token
|
|
@@ -216,7 +216,7 @@ describe "Refresh Token Flow" do
|
|
|
216
216
|
|
|
217
217
|
it "client request a token after creating another token with the same user" do
|
|
218
218
|
post refresh_token_endpoint_url(
|
|
219
|
-
client: @client, refresh_token: @token.refresh_token
|
|
219
|
+
client: @client, refresh_token: @token.refresh_token,
|
|
220
220
|
)
|
|
221
221
|
|
|
222
222
|
should_have_json "refresh_token", last_token.refresh_token
|
|
@@ -226,7 +226,7 @@ describe "Refresh Token Flow" do
|
|
|
226
226
|
|
|
227
227
|
def last_token
|
|
228
228
|
Doorkeeper::AccessToken.last_authorized_token_for(
|
|
229
|
-
@client.id, @resource_owner.id
|
|
229
|
+
@client.id, @resource_owner.id,
|
|
230
230
|
)
|
|
231
231
|
end
|
|
232
232
|
end
|
|
@@ -11,10 +11,12 @@ describe "Revoke Token Flow" do
|
|
|
11
11
|
let(:client_application) { FactoryBot.create :application }
|
|
12
12
|
let(:resource_owner) { User.create!(name: "John", password: "sekret") }
|
|
13
13
|
let(:access_token) do
|
|
14
|
-
FactoryBot.create(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
FactoryBot.create(
|
|
15
|
+
:access_token,
|
|
16
|
+
application: client_application,
|
|
17
|
+
resource_owner_id: resource_owner.id,
|
|
18
|
+
use_refresh_token: true,
|
|
19
|
+
)
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
context "with authenticated, confidential OAuth 2.0 client/application" do
|
|
@@ -40,16 +42,14 @@ describe "Revoke Token Flow" do
|
|
|
40
42
|
end
|
|
41
43
|
|
|
42
44
|
context "with invalid token to revoke" do
|
|
43
|
-
it "should not revoke any tokens and respond
|
|
45
|
+
it "should not revoke any tokens and respond with forbidden" do
|
|
44
46
|
expect do
|
|
45
47
|
post revocation_token_endpoint_url,
|
|
46
48
|
params: { token: "I_AM_AN_INVALID_TOKEN" },
|
|
47
49
|
headers: headers
|
|
48
50
|
end.not_to(change { Doorkeeper::AccessToken.where(revoked_at: nil).count })
|
|
49
51
|
|
|
50
|
-
|
|
51
|
-
# token is invalid
|
|
52
|
-
expect(response).to be_successful
|
|
52
|
+
expect(response).to be_forbidden
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
55
|
|
|
@@ -59,19 +59,23 @@ describe "Revoke Token Flow" do
|
|
|
59
59
|
credentials = Base64.encode64("#{client_id}:poop")
|
|
60
60
|
{ "HTTP_AUTHORIZATION" => "Basic #{credentials}" }
|
|
61
61
|
end
|
|
62
|
-
it "should not revoke any tokens and respond
|
|
62
|
+
it "should not revoke any tokens and respond with forbidden" do
|
|
63
63
|
post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
|
|
64
64
|
|
|
65
|
-
expect(response).to
|
|
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"))
|
|
66
68
|
expect(access_token.reload.revoked?).to be_falsey
|
|
67
69
|
end
|
|
68
70
|
end
|
|
69
71
|
|
|
70
72
|
context "with no credentials and a valid token" do
|
|
71
|
-
it "should not revoke any tokens and respond
|
|
73
|
+
it "should not revoke any tokens and respond with forbidden" do
|
|
72
74
|
post revocation_token_endpoint_url, params: { token: access_token.token }
|
|
73
75
|
|
|
74
|
-
expect(response).to
|
|
76
|
+
expect(response).to be_forbidden
|
|
77
|
+
expect(response.body).to include("unauthorized_client")
|
|
78
|
+
expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
|
|
75
79
|
expect(access_token.reload.revoked?).to be_falsey
|
|
76
80
|
end
|
|
77
81
|
end
|
|
@@ -88,7 +92,9 @@ describe "Revoke Token Flow" do
|
|
|
88
92
|
it "should not revoke the token as its unauthorized" do
|
|
89
93
|
post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
|
|
90
94
|
|
|
91
|
-
expect(response).to
|
|
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"))
|
|
92
98
|
expect(access_token.reload.revoked?).to be_falsey
|
|
93
99
|
end
|
|
94
100
|
end
|
|
@@ -96,10 +102,12 @@ describe "Revoke Token Flow" do
|
|
|
96
102
|
|
|
97
103
|
context "with public OAuth 2.0 client/application" do
|
|
98
104
|
let(:access_token) do
|
|
99
|
-
FactoryBot.create(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
105
|
+
FactoryBot.create(
|
|
106
|
+
:access_token,
|
|
107
|
+
application: nil,
|
|
108
|
+
resource_owner_id: resource_owner.id,
|
|
109
|
+
use_refresh_token: true,
|
|
110
|
+
)
|
|
103
111
|
end
|
|
104
112
|
|
|
105
113
|
it "should revoke the access token provided" do
|
|
@@ -118,23 +126,29 @@ describe "Revoke Token Flow" do
|
|
|
118
126
|
|
|
119
127
|
context "with a valid token issued for a confidential client" do
|
|
120
128
|
let(:access_token) do
|
|
121
|
-
FactoryBot.create(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
129
|
+
FactoryBot.create(
|
|
130
|
+
:access_token,
|
|
131
|
+
application: client_application,
|
|
132
|
+
resource_owner_id: resource_owner.id,
|
|
133
|
+
use_refresh_token: true,
|
|
134
|
+
)
|
|
125
135
|
end
|
|
126
136
|
|
|
127
137
|
it "should not revoke the access token provided" do
|
|
128
138
|
post revocation_token_endpoint_url, params: { token: access_token.token }
|
|
129
139
|
|
|
130
|
-
expect(response).to
|
|
140
|
+
expect(response).to be_forbidden
|
|
141
|
+
expect(response.body).to include("unauthorized_client")
|
|
142
|
+
expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
|
|
131
143
|
expect(access_token.reload.revoked?).to be_falsey
|
|
132
144
|
end
|
|
133
145
|
|
|
134
146
|
it "should not revoke the refresh token provided" do
|
|
135
147
|
post revocation_token_endpoint_url, params: { token: access_token.token }
|
|
136
148
|
|
|
137
|
-
expect(response).to
|
|
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"))
|
|
138
152
|
expect(access_token.reload.revoked?).to be_falsey
|
|
139
153
|
end
|
|
140
154
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -29,12 +29,9 @@ end
|
|
|
29
29
|
|
|
30
30
|
Doorkeeper::RSpec.print_configuration_info
|
|
31
31
|
|
|
32
|
-
# Remove after dropping support of Rails 4.2
|
|
33
|
-
require "#{File.dirname(__FILE__)}/support/http_method_shim"
|
|
34
|
-
|
|
35
32
|
require "support/orm/#{DOORKEEPER_ORM}"
|
|
36
33
|
|
|
37
|
-
Dir["#{File.dirname(__FILE__)}/support/{dependencies,helpers,shared}/*.rb"].each { |file| require file }
|
|
34
|
+
Dir["#{File.dirname(__FILE__)}/support/{dependencies,helpers,shared}/*.rb"].sort.each { |file| require file }
|
|
38
35
|
|
|
39
36
|
RSpec.configure do |config|
|
|
40
37
|
config.infer_spec_type_from_file_location!
|
|
@@ -16,7 +16,7 @@ module Doorkeeper
|
|
|
16
16
|
# Tries to find ORM from the Gemfile used to run test suite
|
|
17
17
|
def self.detect_orm
|
|
18
18
|
orm = (ENV["BUNDLE_GEMFILE"] || "").match(/Gemfile\.(.+)\.rb/)
|
|
19
|
-
(orm && orm[1] || :active_record).to_sym
|
|
19
|
+
(orm && orm[1] || ENV["ORM"] || :active_record).to_sym
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
end
|
|
@@ -54,7 +54,7 @@ module RequestSpecHelper
|
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def with_header(header, value)
|
|
57
|
-
page.driver.header
|
|
57
|
+
page.driver.header(header, value)
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
def basic_auth_header_for_client(client)
|
|
@@ -86,8 +86,20 @@ module RequestSpecHelper
|
|
|
86
86
|
i_should_see translated_error_message(key)
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
+
def i_should_not_see_translated_error_message(key)
|
|
90
|
+
i_should_not_see translated_error_message(key)
|
|
91
|
+
end
|
|
92
|
+
|
|
89
93
|
def translated_error_message(key)
|
|
90
|
-
I18n.translate
|
|
94
|
+
I18n.translate(key, scope: %i[doorkeeper errors messages])
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def i_should_see_translated_invalid_request_error_message(key, value)
|
|
98
|
+
i_should_see translated_invalid_request_error_message(key, value)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def translated_invalid_request_error_message(key, value)
|
|
102
|
+
I18n.translate key, scope: %i[doorkeeper errors messages invalid_request], value: value
|
|
91
103
|
end
|
|
92
104
|
|
|
93
105
|
def response_status_should_be(status)
|
|
@@ -4,14 +4,16 @@ shared_context "valid token", token: :valid do
|
|
|
4
4
|
let(:token_string) { "1A2B3C4D" }
|
|
5
5
|
|
|
6
6
|
let :token do
|
|
7
|
-
double(
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
double(
|
|
8
|
+
Doorkeeper::AccessToken,
|
|
9
|
+
accessible?: true, includes_scope?: true, acceptable?: true,
|
|
10
|
+
previous_refresh_token: "", revoke_previous_refresh_token!: true,
|
|
11
|
+
)
|
|
10
12
|
end
|
|
11
13
|
|
|
12
14
|
before :each do
|
|
13
15
|
allow(
|
|
14
|
-
Doorkeeper::AccessToken
|
|
16
|
+
Doorkeeper::AccessToken,
|
|
15
17
|
).to receive(:by_token).with(token_string).and_return(token)
|
|
16
18
|
end
|
|
17
19
|
end
|
|
@@ -20,15 +22,17 @@ shared_context "invalid token", token: :invalid do
|
|
|
20
22
|
let(:token_string) { "1A2B3C4D" }
|
|
21
23
|
|
|
22
24
|
let :token do
|
|
23
|
-
double(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
double(
|
|
26
|
+
Doorkeeper::AccessToken,
|
|
27
|
+
accessible?: false, revoked?: false, expired?: false,
|
|
28
|
+
includes_scope?: false, acceptable?: false,
|
|
29
|
+
previous_refresh_token: "", revoke_previous_refresh_token!: true,
|
|
30
|
+
)
|
|
27
31
|
end
|
|
28
32
|
|
|
29
33
|
before :each do
|
|
30
34
|
allow(
|
|
31
|
-
Doorkeeper::AccessToken
|
|
35
|
+
Doorkeeper::AccessToken,
|
|
32
36
|
).to receive(:by_token).with(token_string).and_return(token)
|
|
33
37
|
end
|
|
34
38
|
end
|
|
@@ -72,15 +76,17 @@ shared_context "expired token", token: :expired do
|
|
|
72
76
|
end
|
|
73
77
|
|
|
74
78
|
let :token do
|
|
75
|
-
double(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
double(
|
|
80
|
+
Doorkeeper::AccessToken,
|
|
81
|
+
accessible?: false, revoked?: false, expired?: true,
|
|
82
|
+
includes_scope?: false, acceptable?: false,
|
|
83
|
+
previous_refresh_token: "", revoke_previous_refresh_token!: true,
|
|
84
|
+
)
|
|
79
85
|
end
|
|
80
86
|
|
|
81
87
|
before :each do
|
|
82
88
|
allow(
|
|
83
|
-
Doorkeeper::AccessToken
|
|
89
|
+
Doorkeeper::AccessToken,
|
|
84
90
|
).to receive(:by_token).with(token_string).and_return(token)
|
|
85
91
|
end
|
|
86
92
|
end
|
|
@@ -91,15 +97,17 @@ shared_context "revoked token", token: :revoked do
|
|
|
91
97
|
end
|
|
92
98
|
|
|
93
99
|
let :token do
|
|
94
|
-
double(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
100
|
+
double(
|
|
101
|
+
Doorkeeper::AccessToken,
|
|
102
|
+
accessible?: false, revoked?: true, expired?: false,
|
|
103
|
+
includes_scope?: false, acceptable?: false,
|
|
104
|
+
previous_refresh_token: "", revoke_previous_refresh_token!: true,
|
|
105
|
+
)
|
|
98
106
|
end
|
|
99
107
|
|
|
100
108
|
before :each do
|
|
101
109
|
allow(
|
|
102
|
-
Doorkeeper::AccessToken
|
|
110
|
+
Doorkeeper::AccessToken,
|
|
103
111
|
).to receive(:by_token).with(token_string).and_return(token)
|
|
104
112
|
end
|
|
105
113
|
end
|
|
@@ -110,14 +118,16 @@ shared_context "forbidden token", token: :forbidden do
|
|
|
110
118
|
end
|
|
111
119
|
|
|
112
120
|
let :token do
|
|
113
|
-
double(
|
|
114
|
-
|
|
115
|
-
|
|
121
|
+
double(
|
|
122
|
+
Doorkeeper::AccessToken,
|
|
123
|
+
accessible?: true, includes_scope?: true, acceptable?: false,
|
|
124
|
+
previous_refresh_token: "", revoke_previous_refresh_token!: true,
|
|
125
|
+
)
|
|
116
126
|
end
|
|
117
127
|
|
|
118
128
|
before :each do
|
|
119
129
|
allow(
|
|
120
|
-
Doorkeeper::AccessToken
|
|
130
|
+
Doorkeeper::AccessToken,
|
|
121
131
|
).to receive(:by_token).with(token_string).and_return(token)
|
|
122
132
|
end
|
|
123
133
|
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "spec_helper"
|
|
4
4
|
|
|
5
|
-
describe RedirectUriValidator do
|
|
5
|
+
describe Doorkeeper::RedirectUriValidator do
|
|
6
6
|
subject do
|
|
7
7
|
FactoryBot.create(:application)
|
|
8
8
|
end
|
|
@@ -18,7 +18,7 @@ describe RedirectUriValidator do
|
|
|
18
18
|
#
|
|
19
19
|
# @see https://www.oauth.com/oauth2-servers/redirect-uris/redirect-uris-native-apps/
|
|
20
20
|
it "is valid when the uri is custom native URI" do
|
|
21
|
-
subject.redirect_uri = "myapp
|
|
21
|
+
subject.redirect_uri = "myapp:/callback"
|
|
22
22
|
expect(subject).to be_valid
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -27,33 +27,48 @@ describe RedirectUriValidator do
|
|
|
27
27
|
expect(subject).to be_valid
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
it "accepts
|
|
30
|
+
it "accepts nonstandard oob redirect uri" do
|
|
31
31
|
subject.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
|
|
32
32
|
expect(subject).to be_valid
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
it "
|
|
36
|
-
|
|
37
|
-
subject.
|
|
38
|
-
expect(subject).not_to be_valid
|
|
35
|
+
it "accepts nonstandard oob:auto redirect uri" do
|
|
36
|
+
subject.redirect_uri = "urn:ietf:wg:oauth:2.0:oob:auto"
|
|
37
|
+
expect(subject).to be_valid
|
|
39
38
|
end
|
|
40
39
|
|
|
41
40
|
it "is invalid when the uri is not a uri" do
|
|
42
41
|
subject.redirect_uri = "]"
|
|
43
42
|
expect(subject).not_to be_valid
|
|
44
|
-
expect(subject.errors[:redirect_uri].first).to eq("
|
|
43
|
+
expect(subject.errors[:redirect_uri].first).to eq(I18n.t("activerecord.errors.models.doorkeeper/application.attributes.redirect_uri.invalid_uri"))
|
|
45
44
|
end
|
|
46
45
|
|
|
47
46
|
it "is invalid when the uri is relative" do
|
|
48
47
|
subject.redirect_uri = "/abcd"
|
|
49
48
|
expect(subject).not_to be_valid
|
|
50
|
-
expect(subject.errors[:redirect_uri].first).to eq("
|
|
49
|
+
expect(subject.errors[:redirect_uri].first).to eq(I18n.t("activerecord.errors.models.doorkeeper/application.attributes.redirect_uri.relative_uri"))
|
|
51
50
|
end
|
|
52
51
|
|
|
53
52
|
it "is invalid when the uri has a fragment" do
|
|
54
53
|
subject.redirect_uri = "https://example.com/abcd#xyz"
|
|
55
54
|
expect(subject).not_to be_valid
|
|
56
|
-
expect(subject.errors[:redirect_uri].first).to eq("
|
|
55
|
+
expect(subject.errors[:redirect_uri].first).to eq(I18n.t("activerecord.errors.models.doorkeeper/application.attributes.redirect_uri.fragment_present"))
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "is invalid when scheme resolves to localhost (needs an explict scheme)" do
|
|
59
|
+
subject.redirect_uri = "localhost:80"
|
|
60
|
+
expect(subject).to be_invalid
|
|
61
|
+
expect(subject.errors[:redirect_uri].first).to eq(I18n.t("activerecord.errors.models.doorkeeper/application.attributes.redirect_uri.unspecified_scheme"))
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "is invalid if an ip address" do
|
|
65
|
+
subject.redirect_uri = "127.0.0.1:8080"
|
|
66
|
+
expect(subject).to be_invalid
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "accepts an ip address based URI if a scheme is specified" do
|
|
70
|
+
subject.redirect_uri = "https://127.0.0.1:8080"
|
|
71
|
+
expect(subject).to be_valid
|
|
57
72
|
end
|
|
58
73
|
|
|
59
74
|
context "force secured uri" do
|
|
@@ -62,20 +77,30 @@ describe RedirectUriValidator do
|
|
|
62
77
|
expect(subject).to be_valid
|
|
63
78
|
end
|
|
64
79
|
|
|
65
|
-
it "accepts
|
|
66
|
-
subject.redirect_uri = "
|
|
80
|
+
it "accepts custom scheme redirect uri (as per rfc8252 section 7.1)" do
|
|
81
|
+
subject.redirect_uri = "com.example.app:/oauth/callback"
|
|
82
|
+
expect(subject).to be_valid
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "accepts custom scheme redirect uri (as per rfc8252 section 7.1) #2" do
|
|
86
|
+
subject.redirect_uri = "com.example.app:/test"
|
|
87
|
+
expect(subject).to be_valid
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "accepts custom scheme redirect uri (common misconfiguration we have decided to allow)" do
|
|
91
|
+
subject.redirect_uri = "com.example.app://oauth/callback"
|
|
67
92
|
expect(subject).to be_valid
|
|
68
93
|
end
|
|
69
94
|
|
|
70
|
-
it "accepts
|
|
71
|
-
subject.redirect_uri = "
|
|
95
|
+
it "accepts custom scheme redirect uri (common misconfiguration we have decided to allow) #2" do
|
|
96
|
+
subject.redirect_uri = "com.example.app://test"
|
|
72
97
|
expect(subject).to be_valid
|
|
73
98
|
end
|
|
74
99
|
|
|
75
100
|
it "accepts a non secured protocol when disabled" do
|
|
76
101
|
subject.redirect_uri = "http://example.com/callback"
|
|
77
102
|
allow(Doorkeeper.configuration).to receive(
|
|
78
|
-
:force_ssl_in_redirect_uri
|
|
103
|
+
:force_ssl_in_redirect_uri,
|
|
79
104
|
).and_return(false)
|
|
80
105
|
expect(subject).to be_valid
|
|
81
106
|
end
|
|
@@ -118,7 +143,7 @@ describe RedirectUriValidator do
|
|
|
118
143
|
subject.redirect_uri = "http://example.com/callback"
|
|
119
144
|
expect(subject).not_to be_valid
|
|
120
145
|
error = subject.errors[:redirect_uri].first
|
|
121
|
-
expect(error).to eq("
|
|
146
|
+
expect(error).to eq(I18n.t("activerecord.errors.models.doorkeeper/application.attributes.redirect_uri.secured_uri"))
|
|
122
147
|
end
|
|
123
148
|
end
|
|
124
149
|
|