doorkeeper 5.1.2 → 5.2.6
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 +1 -1
- data/CHANGELOG.md +880 -0
- data/CONTRIBUTING.md +11 -9
- data/Dangerfile +2 -2
- data/Dockerfile +29 -0
- data/Gemfile +3 -2
- data/NEWS.md +1 -819
- data/README.md +11 -3
- data/RELEASING.md +6 -5
- data/app/controllers/doorkeeper/application_controller.rb +1 -1
- data/app/controllers/doorkeeper/application_metal_controller.rb +2 -1
- data/app/controllers/doorkeeper/applications_controller.rb +1 -0
- data/app/controllers/doorkeeper/authorizations_controller.rb +14 -7
- 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 +1 -0
- data/gemfiles/rails_5_1.gemfile +1 -0
- data/gemfiles/rails_5_2.gemfile +1 -0
- data/gemfiles/rails_6_0.gemfile +2 -1
- data/gemfiles/rails_master.gemfile +1 -0
- data/lib/doorkeeper/config/option.rb +13 -7
- data/lib/doorkeeper/config.rb +89 -6
- data/lib/doorkeeper/errors.rb +13 -18
- data/lib/doorkeeper/grape/helpers.rb +5 -1
- data/lib/doorkeeper/helpers/controller.rb +23 -4
- data/lib/doorkeeper/models/access_token_mixin.rb +49 -7
- data/lib/doorkeeper/oauth/authorization/code.rb +11 -13
- data/lib/doorkeeper/oauth/authorization/token.rb +1 -1
- data/lib/doorkeeper/oauth/authorization_code_request.rb +18 -9
- data/lib/doorkeeper/oauth/base_request.rb +2 -0
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +14 -0
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +8 -0
- data/lib/doorkeeper/oauth/code_request.rb +5 -11
- data/lib/doorkeeper/oauth/code_response.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +18 -4
- data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
- data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
- data/lib/doorkeeper/oauth/pre_authorization.rb +73 -37
- data/lib/doorkeeper/oauth/refresh_token_request.rb +13 -10
- data/lib/doorkeeper/oauth/token_introspection.rb +23 -13
- data/lib/doorkeeper/oauth/token_request.rb +4 -18
- data/lib/doorkeeper/orm/active_record/access_grant.rb +1 -1
- data/lib/doorkeeper/orm/active_record/access_token.rb +2 -2
- data/lib/doorkeeper/orm/active_record/application.rb +13 -5
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +61 -0
- data/lib/doorkeeper/orm/active_record.rb +18 -3
- data/lib/doorkeeper/request/authorization_code.rb +2 -0
- data/lib/doorkeeper/request.rb +6 -11
- data/lib/doorkeeper/server.rb +2 -6
- data/lib/doorkeeper/stale_records_cleaner.rb +6 -2
- data/lib/doorkeeper/version.rb +2 -2
- data/lib/doorkeeper.rb +4 -0
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +6 -6
- data/lib/generators/doorkeeper/templates/initializer.rb +118 -33
- data/lib/generators/doorkeeper/templates/migration.rb.erb +4 -1
- data/spec/controllers/applications_controller_spec.rb +93 -0
- data/spec/controllers/authorizations_controller_spec.rb +143 -62
- data/spec/controllers/protected_resources_controller_spec.rb +3 -3
- data/spec/controllers/tokens_controller_spec.rb +205 -37
- 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 +1 -1
- data/spec/lib/config_spec.rb +58 -1
- data/spec/lib/oauth/authorization_code_request_spec.rb +13 -1
- data/spec/lib/oauth/base_request_spec.rb +33 -16
- data/spec/lib/oauth/client_credentials/creator_spec.rb +3 -0
- data/spec/lib/oauth/code_request_spec.rb +27 -28
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +17 -2
- data/spec/lib/oauth/invalid_request_response_spec.rb +75 -0
- data/spec/lib/oauth/pre_authorization_spec.rb +76 -66
- data/spec/lib/oauth/refresh_token_request_spec.rb +1 -0
- data/spec/lib/oauth/token_request_spec.rb +20 -17
- data/spec/lib/server_spec.rb +0 -12
- data/spec/models/doorkeeper/access_grant_spec.rb +21 -2
- data/spec/models/doorkeeper/access_token_spec.rb +35 -4
- data/spec/models/doorkeeper/application_spec.rb +10 -0
- data/spec/requests/endpoints/authorization_spec.rb +21 -5
- 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 +93 -27
- 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 +37 -0
- data/spec/requests/flows/refresh_token_spec.rb +1 -1
- data/spec/requests/flows/revoke_token_spec.rb +19 -11
- data/spec/support/doorkeeper_rspec.rb +1 -1
- data/spec/support/helpers/request_spec_helper.rb +14 -2
- data/spec/validators/redirect_uri_validator_spec.rb +40 -15
- metadata +16 -15
- 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
@@ -14,23 +14,23 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
def translated_error_message(key)
|
18
|
-
I18n.translate key, scope: %i[doorkeeper errors messages]
|
19
|
-
end
|
20
|
-
|
21
17
|
let(:client) { FactoryBot.create :application }
|
22
18
|
let(:user) { User.create!(name: "Joe", password: "sekret") }
|
23
|
-
let(:access_token) { FactoryBot.build :access_token, resource_owner_id: user.id, application_id: client.id }
|
19
|
+
let(:access_token) { FactoryBot.build :access_token, resource_owner_id: user.id, application_id: client.id, scopes: "default" }
|
24
20
|
|
25
21
|
before do
|
26
22
|
Doorkeeper.configure do
|
23
|
+
default_scopes :default
|
24
|
+
|
27
25
|
custom_access_token_expires_in(lambda do |context|
|
28
26
|
context.grant_type == Doorkeeper::OAuth::IMPLICIT ? 1234 : nil
|
29
27
|
end)
|
30
28
|
end
|
31
29
|
|
32
30
|
allow(Doorkeeper.configuration).to receive(:grant_flows).and_return(["implicit"])
|
33
|
-
allow(
|
31
|
+
allow(Doorkeeper.configuration).to receive(:authenticate_resource_owner).and_return(->(_) { authenticator_method })
|
32
|
+
allow(controller).to receive(:authenticator_method).and_return(user)
|
33
|
+
expect(controller).to receive(:authenticator_method).at_most(:once)
|
34
34
|
end
|
35
35
|
|
36
36
|
describe "POST #create" do
|
@@ -106,80 +106,146 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
|
|
106
106
|
end
|
107
107
|
|
108
108
|
describe "POST #create with errors" do
|
109
|
-
|
110
|
-
|
109
|
+
context "when missing client_id" do
|
110
|
+
before do
|
111
|
+
post :create, params: {
|
112
|
+
client_id: "",
|
113
|
+
response_type: "token",
|
114
|
+
redirect_uri: client.redirect_uri,
|
115
|
+
}
|
116
|
+
end
|
111
117
|
|
112
|
-
|
113
|
-
client_id: client.uid,
|
114
|
-
response_type: "token",
|
115
|
-
scope: "invalid",
|
116
|
-
redirect_uri: client.redirect_uri,
|
117
|
-
}
|
118
|
-
end
|
118
|
+
let(:response_json_body) { JSON.parse(response.body) }
|
119
119
|
|
120
|
-
|
121
|
-
|
122
|
-
|
120
|
+
it "renders 400 error" do
|
121
|
+
expect(response.status).to eq 400
|
122
|
+
end
|
123
123
|
|
124
|
-
|
125
|
-
|
126
|
-
|
124
|
+
it "includes error name" do
|
125
|
+
expect(response_json_body["error"]).to eq("invalid_request")
|
126
|
+
end
|
127
127
|
|
128
|
-
|
129
|
-
|
130
|
-
|
128
|
+
it "includes error description" do
|
129
|
+
expect(response_json_body["error_description"]).to eq(
|
130
|
+
translated_invalid_request_error_message(:missing_param, :client_id)
|
131
|
+
)
|
132
|
+
end
|
131
133
|
|
132
|
-
|
133
|
-
|
134
|
+
it "does not issue any access token" do
|
135
|
+
expect(Doorkeeper::AccessToken.all).to be_empty
|
136
|
+
end
|
134
137
|
end
|
135
138
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
+
context "when other error happens" do
|
140
|
+
before do
|
141
|
+
default_scopes_exist :public
|
142
|
+
|
143
|
+
post :create, params: {
|
144
|
+
client_id: client.uid,
|
145
|
+
response_type: "token",
|
146
|
+
scope: "invalid",
|
147
|
+
redirect_uri: client.redirect_uri,
|
148
|
+
}
|
149
|
+
end
|
150
|
+
|
151
|
+
it "redirects after authorization" do
|
152
|
+
expect(response).to be_redirect
|
153
|
+
end
|
154
|
+
|
155
|
+
it "redirects to client redirect uri" do
|
156
|
+
expect(response.location).to match(/^#{client.redirect_uri}/)
|
157
|
+
end
|
158
|
+
|
159
|
+
it "does not include access token in fragment" do
|
160
|
+
expect(response.query_params["access_token"]).to be_nil
|
161
|
+
end
|
162
|
+
|
163
|
+
it "includes error in fragment" do
|
164
|
+
expect(response.query_params["error"]).to eq("invalid_scope")
|
165
|
+
end
|
166
|
+
|
167
|
+
it "includes error description in fragment" do
|
168
|
+
expect(response.query_params["error_description"]).to eq(translated_error_message(:invalid_scope))
|
169
|
+
end
|
139
170
|
|
140
|
-
|
141
|
-
|
171
|
+
it "does not issue any access token" do
|
172
|
+
expect(Doorkeeper::AccessToken.all).to be_empty
|
173
|
+
end
|
142
174
|
end
|
143
175
|
end
|
144
176
|
|
145
177
|
describe "POST #create in API mode with errors" do
|
146
|
-
|
147
|
-
|
148
|
-
|
178
|
+
context "when missing client_id" do
|
179
|
+
before do
|
180
|
+
allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
|
149
181
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
end
|
182
|
+
post :create, params: {
|
183
|
+
client_id: "",
|
184
|
+
response_type: "token",
|
185
|
+
redirect_uri: client.redirect_uri,
|
186
|
+
}
|
187
|
+
end
|
157
188
|
|
158
|
-
|
159
|
-
let(:redirect_uri) { response_json_body["redirect_uri"] }
|
189
|
+
let(:response_json_body) { JSON.parse(response.body) }
|
160
190
|
|
161
|
-
|
162
|
-
|
163
|
-
|
191
|
+
it "renders 400 error" do
|
192
|
+
expect(response.status).to eq 400
|
193
|
+
end
|
164
194
|
|
165
|
-
|
166
|
-
|
167
|
-
|
195
|
+
it "includes error name" do
|
196
|
+
expect(response_json_body["error"]).to eq("invalid_request")
|
197
|
+
end
|
168
198
|
|
169
|
-
|
170
|
-
|
171
|
-
|
199
|
+
it "includes error description" do
|
200
|
+
expect(response_json_body["error_description"]).to eq(
|
201
|
+
translated_invalid_request_error_message(:missing_param, :client_id)
|
202
|
+
)
|
203
|
+
end
|
172
204
|
|
173
|
-
|
174
|
-
|
205
|
+
it "does not issue any access token" do
|
206
|
+
expect(Doorkeeper::AccessToken.all).to be_empty
|
207
|
+
end
|
175
208
|
end
|
176
209
|
|
177
|
-
|
178
|
-
|
179
|
-
|
210
|
+
context "when other error happens" do
|
211
|
+
before do
|
212
|
+
allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
|
213
|
+
default_scopes_exist :public
|
180
214
|
|
181
|
-
|
182
|
-
|
215
|
+
post :create, params: {
|
216
|
+
client_id: client.uid,
|
217
|
+
response_type: "token",
|
218
|
+
scope: "invalid",
|
219
|
+
redirect_uri: client.redirect_uri,
|
220
|
+
}
|
221
|
+
end
|
222
|
+
|
223
|
+
let(:response_json_body) { JSON.parse(response.body) }
|
224
|
+
let(:redirect_uri) { response_json_body["redirect_uri"] }
|
225
|
+
|
226
|
+
it "renders 400 error" do
|
227
|
+
expect(response.status).to eq 400
|
228
|
+
end
|
229
|
+
|
230
|
+
it "includes correct redirect URI" do
|
231
|
+
expect(redirect_uri).to match(/^#{client.redirect_uri}/)
|
232
|
+
end
|
233
|
+
|
234
|
+
it "does not include access token in fragment" do
|
235
|
+
expect(redirect_uri.match(/access_token=([a-f0-9]+)&?/)).to be_nil
|
236
|
+
end
|
237
|
+
|
238
|
+
it "includes error in redirect uri" do
|
239
|
+
expect(redirect_uri.match(/error=([a-z_]+)&?/)[1]).to eq "invalid_scope"
|
240
|
+
end
|
241
|
+
|
242
|
+
it "includes error description in redirect uri" do
|
243
|
+
expect(redirect_uri.match(/error_description=(.+)&?/)[1]).to_not be_nil
|
244
|
+
end
|
245
|
+
|
246
|
+
it "does not issue any access token" do
|
247
|
+
expect(Doorkeeper::AccessToken.all).to be_empty
|
248
|
+
end
|
183
249
|
end
|
184
250
|
end
|
185
251
|
|
@@ -368,7 +434,7 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
|
|
368
434
|
expect(json_response["redirect_uri"]).to eq(client.redirect_uri)
|
369
435
|
expect(json_response["state"]).to be_nil
|
370
436
|
expect(json_response["response_type"]).to eq("token")
|
371
|
-
expect(json_response["scope"]).to eq("")
|
437
|
+
expect(json_response["scope"]).to eq("default")
|
372
438
|
end
|
373
439
|
end
|
374
440
|
|
@@ -445,12 +511,12 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
|
|
445
511
|
end
|
446
512
|
|
447
513
|
it "includes error in body" do
|
448
|
-
expect(response_json_body["error"]).to eq("
|
514
|
+
expect(response_json_body["error"]).to eq("invalid_request")
|
449
515
|
end
|
450
516
|
|
451
517
|
it "includes error description in body" do
|
452
518
|
expect(response_json_body["error_description"])
|
453
|
-
.to eq(
|
519
|
+
.to eq(translated_invalid_request_error_message(:missing_param, :client_id))
|
454
520
|
end
|
455
521
|
|
456
522
|
it "does not issue any token" do
|
@@ -513,6 +579,8 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
|
|
513
579
|
|
514
580
|
describe "authorize response memoization" do
|
515
581
|
it "memoizes the result of the authorization" do
|
582
|
+
pre_auth = double(:pre_auth, authorizable?: true)
|
583
|
+
allow(controller).to receive(:pre_auth) { pre_auth }
|
516
584
|
strategy = double(:strategy, authorize: true)
|
517
585
|
expect(strategy).to receive(:authorize).once
|
518
586
|
allow(controller).to receive(:strategy) { strategy }
|
@@ -524,4 +592,17 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
|
|
524
592
|
post :create
|
525
593
|
end
|
526
594
|
end
|
595
|
+
|
596
|
+
describe "strong parameters" do
|
597
|
+
it "ignores non-scalar scope parameter" do
|
598
|
+
get :new, params: {
|
599
|
+
client_id: client.uid,
|
600
|
+
response_type: "token",
|
601
|
+
redirect_uri: client.redirect_uri,
|
602
|
+
scope: { "0" => "profile" },
|
603
|
+
}
|
604
|
+
|
605
|
+
expect(response).to be_successful
|
606
|
+
end
|
607
|
+
end
|
527
608
|
end
|
@@ -166,7 +166,7 @@ describe "doorkeeper authorize filter" do
|
|
166
166
|
it "it renders a custom JSON response", token: :invalid do
|
167
167
|
get :index, params: { access_token: token_string }
|
168
168
|
expect(response.status).to eq 401
|
169
|
-
expect(response.content_type).to
|
169
|
+
expect(response.content_type).to include("application/json")
|
170
170
|
expect(response.header["WWW-Authenticate"]).to match(/^Bearer/)
|
171
171
|
|
172
172
|
expect(json_response).not_to be_nil
|
@@ -196,7 +196,7 @@ describe "doorkeeper authorize filter" do
|
|
196
196
|
it "it renders a custom text response", token: :invalid do
|
197
197
|
get :index, params: { access_token: token_string }
|
198
198
|
expect(response.status).to eq 401
|
199
|
-
expect(response.content_type).to
|
199
|
+
expect(response.content_type).to include("text/plain")
|
200
200
|
expect(response.header["WWW-Authenticate"]).to match(/^Bearer/)
|
201
201
|
expect(response.body).to eq("Unauthorized")
|
202
202
|
end
|
@@ -246,7 +246,7 @@ describe "doorkeeper authorize filter" do
|
|
246
246
|
it "renders a custom JSON response" do
|
247
247
|
get :index, params: { access_token: token_string }
|
248
248
|
expect(response.header).to_not include("WWW-Authenticate")
|
249
|
-
expect(response.content_type).to
|
249
|
+
expect(response.content_type).to include("application/json")
|
250
250
|
expect(response.status).to eq 403
|
251
251
|
|
252
252
|
expect(json_response).not_to be_nil
|
@@ -3,31 +3,139 @@
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
5
|
describe Doorkeeper::TokensController do
|
6
|
-
|
7
|
-
|
6
|
+
let(:client) { FactoryBot.create :application }
|
7
|
+
let!(:user) { User.create!(name: "Joe", password: "sekret") }
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
before do
|
10
|
+
Doorkeeper.configure do
|
11
|
+
resource_owner_from_credentials do
|
12
|
+
User.first
|
13
|
+
end
|
14
|
+
end
|
11
15
|
|
12
|
-
|
16
|
+
allow(Doorkeeper.configuration).to receive(:grant_flows).and_return(["password"])
|
17
|
+
end
|
13
18
|
|
14
|
-
|
19
|
+
subject { JSON.parse(response.body) }
|
20
|
+
|
21
|
+
describe "POST #create" do
|
22
|
+
before do
|
23
|
+
post :create, params: {
|
24
|
+
client_id: client.uid,
|
25
|
+
client_secret: client.secret,
|
26
|
+
grant_type: "password",
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
it "responds after authorization" do
|
31
|
+
expect(response).to be_successful
|
32
|
+
end
|
33
|
+
|
34
|
+
it "includes access token in response" do
|
35
|
+
expect(subject["access_token"]).to eq(Doorkeeper::AccessToken.first.token)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "includes token type in response" do
|
39
|
+
expect(subject["token_type"]).to eq("Bearer")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "includes token expiration in response" do
|
43
|
+
expect(subject["expires_in"].to_i).to eq(Doorkeeper.configuration.access_token_expires_in)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "issues the token for the current client" do
|
47
|
+
expect(Doorkeeper::AccessToken.first.application_id).to eq(client.id)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "issues the token for the current resource owner" do
|
51
|
+
expect(Doorkeeper::AccessToken.first.resource_owner_id).to eq(user.id)
|
15
52
|
end
|
16
53
|
end
|
17
54
|
|
18
|
-
describe "
|
19
|
-
|
20
|
-
|
21
|
-
|
55
|
+
describe "POST #create with errors" do
|
56
|
+
before do
|
57
|
+
post :create, params: {
|
58
|
+
client_id: client.uid,
|
59
|
+
client_secret: "invalid",
|
60
|
+
grant_type: "password",
|
61
|
+
}
|
62
|
+
end
|
22
63
|
|
23
|
-
|
64
|
+
it "responds after authorization" do
|
65
|
+
expect(response).to be_unauthorized
|
66
|
+
end
|
24
67
|
|
25
|
-
|
26
|
-
expect(
|
68
|
+
it "include error in response" do
|
69
|
+
expect(subject["error"]).to eq("invalid_client")
|
70
|
+
end
|
71
|
+
|
72
|
+
it "include error_description in response" do
|
73
|
+
expect(subject["error_description"]).to be
|
74
|
+
end
|
75
|
+
|
76
|
+
it "does not include access token in response" do
|
77
|
+
expect(subject["access_token"]).to be_nil
|
78
|
+
end
|
79
|
+
|
80
|
+
it "does not include token type in response" do
|
81
|
+
expect(subject["token_type"]).to be_nil
|
82
|
+
end
|
83
|
+
|
84
|
+
it "does not include token expiration in response" do
|
85
|
+
expect(subject["expires_in"]).to be_nil
|
86
|
+
end
|
87
|
+
|
88
|
+
it "does not issue any access token" do
|
89
|
+
expect(Doorkeeper::AccessToken.all).to be_empty
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "POST #create with callbacks" do
|
94
|
+
after do
|
95
|
+
client.update_attribute :redirect_uri, "urn:ietf:wg:oauth:2.0:oob"
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "when successful" do
|
99
|
+
after do
|
100
|
+
post :create, params: {
|
101
|
+
client_id: client.uid,
|
102
|
+
client_secret: client.secret,
|
103
|
+
grant_type: "password",
|
104
|
+
}
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should call :before_successful_authorization callback" do
|
108
|
+
expect(Doorkeeper.configuration)
|
109
|
+
.to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should call :after_successful_authorization callback" do
|
113
|
+
expect(Doorkeeper.configuration)
|
114
|
+
.to receive_message_chain(:after_successful_authorization, :call).with(instance_of(described_class))
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "with errors" do
|
119
|
+
after do
|
120
|
+
post :create, params: {
|
121
|
+
client_id: client.uid,
|
122
|
+
client_secret: "invalid",
|
123
|
+
grant_type: "password",
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should call :before_successful_authorization callback" do
|
128
|
+
expect(Doorkeeper.configuration)
|
129
|
+
.to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should not call :after_successful_authorization callback" do
|
133
|
+
expect(Doorkeeper.configuration).not_to receive(:after_successful_authorization)
|
134
|
+
end
|
27
135
|
end
|
28
136
|
end
|
29
137
|
|
30
|
-
describe "
|
138
|
+
describe "POST #create with custom error" do
|
31
139
|
it "returns the error response with a custom message" do
|
32
140
|
# I18n looks for `doorkeeper.errors.messages.custom_message` in locale files
|
33
141
|
custom_message = "my_message"
|
@@ -58,7 +166,7 @@ describe Doorkeeper::TokensController do
|
|
58
166
|
end
|
59
167
|
|
60
168
|
# http://tools.ietf.org/html/rfc7009#section-2.2
|
61
|
-
describe "
|
169
|
+
describe "POST #revoke" do
|
62
170
|
let(:client) { FactoryBot.create(:application) }
|
63
171
|
let(:access_token) { FactoryBot.create(:access_token, application: client) }
|
64
172
|
|
@@ -102,10 +210,10 @@ describe Doorkeeper::TokensController do
|
|
102
210
|
let(:some_other_client) { FactoryBot.create(:application, confidential: true) }
|
103
211
|
let(:oauth_client) { Doorkeeper::OAuth::Client.new(some_other_client) }
|
104
212
|
|
105
|
-
it "returns
|
213
|
+
it "returns 403" do
|
106
214
|
post :revoke, params: { token: access_token.token }
|
107
215
|
|
108
|
-
expect(response.status).to eq
|
216
|
+
expect(response.status).to eq 403
|
109
217
|
end
|
110
218
|
|
111
219
|
it "does not revoke the access token" do
|
@@ -117,21 +225,7 @@ describe Doorkeeper::TokensController do
|
|
117
225
|
end
|
118
226
|
end
|
119
227
|
|
120
|
-
describe "
|
121
|
-
it "memoizes the result of the authorization" do
|
122
|
-
strategy = double(:strategy, authorize: true)
|
123
|
-
expect(strategy).to receive(:authorize).once
|
124
|
-
allow(controller).to receive(:strategy) { strategy }
|
125
|
-
allow(controller).to receive(:create) do
|
126
|
-
2.times { controller.send :authorize_response }
|
127
|
-
controller.render json: {}, status: :ok
|
128
|
-
end
|
129
|
-
|
130
|
-
post :create
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
describe "when requested token introspection" do
|
228
|
+
describe "POST #introspect" do
|
135
229
|
let(:client) { FactoryBot.create(:application) }
|
136
230
|
let(:access_token) { FactoryBot.create(:access_token, application: client) }
|
137
231
|
let(:token_for_introspection) { FactoryBot.create(:access_token, application: client) }
|
@@ -147,7 +241,7 @@ describe Doorkeeper::TokensController do
|
|
147
241
|
end
|
148
242
|
end
|
149
243
|
|
150
|
-
context "authorized using
|
244
|
+
context "authorized using Client Credentials of the client that token is issued to" do
|
151
245
|
it "responds with full token introspection" do
|
152
246
|
request.headers["Authorization"] = basic_auth_header_for_client(client)
|
153
247
|
|
@@ -159,6 +253,26 @@ describe Doorkeeper::TokensController do
|
|
159
253
|
end
|
160
254
|
end
|
161
255
|
|
256
|
+
context "configured token introspection disabled" do
|
257
|
+
before do
|
258
|
+
Doorkeeper.configure do
|
259
|
+
orm DOORKEEPER_ORM
|
260
|
+
allow_token_introspection false
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
it "responds with invalid_token error" do
|
265
|
+
request.headers["Authorization"] = "Bearer #{access_token.token}"
|
266
|
+
|
267
|
+
post :introspect, params: { token: token_for_introspection.token }
|
268
|
+
|
269
|
+
response_status_should_be 401
|
270
|
+
|
271
|
+
should_not_have_json "active"
|
272
|
+
should_have_json "error", "invalid_token"
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
162
276
|
context "using custom introspection response" do
|
163
277
|
before do
|
164
278
|
Doorkeeper.configure do
|
@@ -212,12 +326,64 @@ describe Doorkeeper::TokensController do
|
|
212
326
|
end
|
213
327
|
end
|
214
328
|
|
329
|
+
context "introspection request authorized by a client and allow_token_introspection is true" do
|
330
|
+
let(:different_client) { FactoryBot.create(:application) }
|
331
|
+
|
332
|
+
before do
|
333
|
+
allow(Doorkeeper.configuration).to receive(:allow_token_introspection).and_return(proc do
|
334
|
+
true
|
335
|
+
end)
|
336
|
+
end
|
337
|
+
|
338
|
+
it "responds with full token introspection" do
|
339
|
+
request.headers["Authorization"] = basic_auth_header_for_client(different_client)
|
340
|
+
|
341
|
+
post :introspect, params: { token: token_for_introspection.token }
|
342
|
+
|
343
|
+
should_have_json "active", true
|
344
|
+
expect(json_response).to include("client_id", "token_type", "exp", "iat")
|
345
|
+
should_have_json "client_id", client.uid
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
context "allow_token_introspection requires authorized token with special scope" do
|
350
|
+
let(:access_token) { FactoryBot.create(:access_token, scopes: "introspection") }
|
351
|
+
|
352
|
+
before do
|
353
|
+
allow(Doorkeeper.configuration).to receive(:allow_token_introspection).and_return(proc do |_token, _client, authorized_token|
|
354
|
+
authorized_token.scopes.include?("introspection")
|
355
|
+
end)
|
356
|
+
end
|
357
|
+
|
358
|
+
it "responds with full token introspection if authorized token has introspection scope" do
|
359
|
+
request.headers["Authorization"] = "Bearer #{access_token.token}"
|
360
|
+
|
361
|
+
post :introspect, params: { token: token_for_introspection.token }
|
362
|
+
|
363
|
+
should_have_json "active", true
|
364
|
+
expect(json_response).to include("client_id", "token_type", "exp", "iat")
|
365
|
+
end
|
366
|
+
|
367
|
+
it "responds with invalid_token error if authorized token doesn't have introspection scope" do
|
368
|
+
access_token.update(scopes: "read write")
|
369
|
+
|
370
|
+
request.headers["Authorization"] = "Bearer #{access_token.token}"
|
371
|
+
|
372
|
+
post :introspect, params: { token: token_for_introspection.token }
|
373
|
+
|
374
|
+
response_status_should_be 401
|
375
|
+
|
376
|
+
should_not_have_json "active"
|
377
|
+
should_have_json "error", "invalid_token"
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
215
381
|
context "authorized using invalid Bearer token" do
|
216
382
|
let(:access_token) do
|
217
383
|
FactoryBot.create(:access_token, application: client, revoked_at: 1.day.ago)
|
218
384
|
end
|
219
385
|
|
220
|
-
it "responds with
|
386
|
+
it "responds with invalid_token error" do
|
221
387
|
request.headers["Authorization"] = "Bearer #{access_token.token}"
|
222
388
|
|
223
389
|
post :introspect, params: { token: token_for_introspection.token }
|
@@ -272,13 +438,15 @@ describe Doorkeeper::TokensController do
|
|
272
438
|
end
|
273
439
|
|
274
440
|
context "authorized using valid Bearer token" do
|
275
|
-
it "responds with
|
441
|
+
it "responds with invalid_token error" do
|
276
442
|
request.headers["Authorization"] = "Bearer #{access_token.token}"
|
277
443
|
|
278
444
|
post :introspect, params: { token: SecureRandom.hex(16) }
|
279
445
|
|
280
|
-
|
281
|
-
|
446
|
+
response_status_should_be 401
|
447
|
+
|
448
|
+
should_not_have_json "active"
|
449
|
+
should_have_json "error", "invalid_token"
|
282
450
|
end
|
283
451
|
end
|
284
452
|
end
|
@@ -5,11 +5,13 @@ require "rails"
|
|
5
5
|
%w[
|
6
6
|
action_controller/railtie
|
7
7
|
action_view/railtie
|
8
|
+
action_cable/engine
|
8
9
|
sprockets/railtie
|
9
10
|
].each do |railtie|
|
10
11
|
begin
|
11
12
|
require railtie
|
12
|
-
rescue LoadError
|
13
|
+
rescue LoadError => e
|
14
|
+
puts "Error loading '#{railtie}' (#{e.message})"
|
13
15
|
end
|
14
16
|
end
|
15
17
|
|