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.

Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +1 -1
  3. data/CHANGELOG.md +880 -0
  4. data/CONTRIBUTING.md +11 -9
  5. data/Dangerfile +2 -2
  6. data/Dockerfile +29 -0
  7. data/Gemfile +3 -2
  8. data/NEWS.md +1 -819
  9. data/README.md +11 -3
  10. data/RELEASING.md +6 -5
  11. data/app/controllers/doorkeeper/application_controller.rb +1 -1
  12. data/app/controllers/doorkeeper/application_metal_controller.rb +2 -1
  13. data/app/controllers/doorkeeper/applications_controller.rb +1 -0
  14. data/app/controllers/doorkeeper/authorizations_controller.rb +14 -7
  15. data/app/controllers/doorkeeper/tokens_controller.rb +32 -9
  16. data/app/views/doorkeeper/applications/_form.html.erb +0 -6
  17. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  18. data/config/locales/en.yml +8 -2
  19. data/doorkeeper.gemspec +9 -1
  20. data/gemfiles/rails_5_0.gemfile +1 -0
  21. data/gemfiles/rails_5_1.gemfile +1 -0
  22. data/gemfiles/rails_5_2.gemfile +1 -0
  23. data/gemfiles/rails_6_0.gemfile +2 -1
  24. data/gemfiles/rails_master.gemfile +1 -0
  25. data/lib/doorkeeper/config/option.rb +13 -7
  26. data/lib/doorkeeper/config.rb +89 -6
  27. data/lib/doorkeeper/errors.rb +13 -18
  28. data/lib/doorkeeper/grape/helpers.rb +5 -1
  29. data/lib/doorkeeper/helpers/controller.rb +23 -4
  30. data/lib/doorkeeper/models/access_token_mixin.rb +49 -7
  31. data/lib/doorkeeper/oauth/authorization/code.rb +11 -13
  32. data/lib/doorkeeper/oauth/authorization/token.rb +1 -1
  33. data/lib/doorkeeper/oauth/authorization_code_request.rb +18 -9
  34. data/lib/doorkeeper/oauth/base_request.rb +2 -0
  35. data/lib/doorkeeper/oauth/client_credentials/creator.rb +14 -0
  36. data/lib/doorkeeper/oauth/client_credentials/validation.rb +8 -0
  37. data/lib/doorkeeper/oauth/code_request.rb +5 -11
  38. data/lib/doorkeeper/oauth/code_response.rb +2 -2
  39. data/lib/doorkeeper/oauth/error_response.rb +1 -1
  40. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +18 -4
  41. data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
  42. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  43. data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
  44. data/lib/doorkeeper/oauth/pre_authorization.rb +73 -37
  45. data/lib/doorkeeper/oauth/refresh_token_request.rb +13 -10
  46. data/lib/doorkeeper/oauth/token_introspection.rb +23 -13
  47. data/lib/doorkeeper/oauth/token_request.rb +4 -18
  48. data/lib/doorkeeper/orm/active_record/access_grant.rb +1 -1
  49. data/lib/doorkeeper/orm/active_record/access_token.rb +2 -2
  50. data/lib/doorkeeper/orm/active_record/application.rb +13 -5
  51. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +61 -0
  52. data/lib/doorkeeper/orm/active_record.rb +18 -3
  53. data/lib/doorkeeper/request/authorization_code.rb +2 -0
  54. data/lib/doorkeeper/request.rb +6 -11
  55. data/lib/doorkeeper/server.rb +2 -6
  56. data/lib/doorkeeper/stale_records_cleaner.rb +6 -2
  57. data/lib/doorkeeper/version.rb +2 -2
  58. data/lib/doorkeeper.rb +4 -0
  59. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +6 -6
  60. data/lib/generators/doorkeeper/templates/initializer.rb +118 -33
  61. data/lib/generators/doorkeeper/templates/migration.rb.erb +4 -1
  62. data/spec/controllers/applications_controller_spec.rb +93 -0
  63. data/spec/controllers/authorizations_controller_spec.rb +143 -62
  64. data/spec/controllers/protected_resources_controller_spec.rb +3 -3
  65. data/spec/controllers/tokens_controller_spec.rb +205 -37
  66. data/spec/dummy/config/application.rb +3 -1
  67. data/spec/dummy/config/initializers/doorkeeper.rb +54 -9
  68. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +1 -1
  69. data/spec/lib/config_spec.rb +58 -1
  70. data/spec/lib/oauth/authorization_code_request_spec.rb +13 -1
  71. data/spec/lib/oauth/base_request_spec.rb +33 -16
  72. data/spec/lib/oauth/client_credentials/creator_spec.rb +3 -0
  73. data/spec/lib/oauth/code_request_spec.rb +27 -28
  74. data/spec/lib/oauth/helpers/uri_checker_spec.rb +17 -2
  75. data/spec/lib/oauth/invalid_request_response_spec.rb +75 -0
  76. data/spec/lib/oauth/pre_authorization_spec.rb +76 -66
  77. data/spec/lib/oauth/refresh_token_request_spec.rb +1 -0
  78. data/spec/lib/oauth/token_request_spec.rb +20 -17
  79. data/spec/lib/server_spec.rb +0 -12
  80. data/spec/models/doorkeeper/access_grant_spec.rb +21 -2
  81. data/spec/models/doorkeeper/access_token_spec.rb +35 -4
  82. data/spec/models/doorkeeper/application_spec.rb +10 -0
  83. data/spec/requests/endpoints/authorization_spec.rb +21 -5
  84. data/spec/requests/endpoints/token_spec.rb +1 -1
  85. data/spec/requests/flows/authorization_code_errors_spec.rb +1 -0
  86. data/spec/requests/flows/authorization_code_spec.rb +93 -27
  87. data/spec/requests/flows/client_credentials_spec.rb +38 -0
  88. data/spec/requests/flows/implicit_grant_errors_spec.rb +22 -10
  89. data/spec/requests/flows/implicit_grant_spec.rb +9 -8
  90. data/spec/requests/flows/password_spec.rb +37 -0
  91. data/spec/requests/flows/refresh_token_spec.rb +1 -1
  92. data/spec/requests/flows/revoke_token_spec.rb +19 -11
  93. data/spec/support/doorkeeper_rspec.rb +1 -1
  94. data/spec/support/helpers/request_spec_helper.rb +14 -2
  95. data/spec/validators/redirect_uri_validator_spec.rb +40 -15
  96. metadata +16 -15
  97. data/.coveralls.yml +0 -1
  98. data/.github/ISSUE_TEMPLATE.md +0 -25
  99. data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  100. data/.gitignore +0 -20
  101. data/.gitlab-ci.yml +0 -16
  102. data/.hound.yml +0 -3
  103. data/.rspec +0 -1
  104. data/.rubocop.yml +0 -50
  105. data/.travis.yml +0 -35
  106. 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(controller).to receive(:current_resource_owner).and_return(user)
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
- before do
110
- default_scopes_exist :public
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
- post :create, params: {
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
- it "redirects after authorization" do
121
- expect(response).to be_redirect
122
- end
120
+ it "renders 400 error" do
121
+ expect(response.status).to eq 400
122
+ end
123
123
 
124
- it "redirects to client redirect uri" do
125
- expect(response.location).to match(/^#{client.redirect_uri}/)
126
- end
124
+ it "includes error name" do
125
+ expect(response_json_body["error"]).to eq("invalid_request")
126
+ end
127
127
 
128
- it "does not include access token in fragment" do
129
- expect(response.query_params["access_token"]).to be_nil
130
- end
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
- it "includes error in fragment" do
133
- expect(response.query_params["error"]).to eq("invalid_scope")
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
- it "includes error description in fragment" do
137
- expect(response.query_params["error_description"]).to eq(translated_error_message(:invalid_scope))
138
- end
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
- it "does not issue any access token" do
141
- expect(Doorkeeper::AccessToken.all).to be_empty
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
- before do
147
- allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
148
- default_scopes_exist :public
178
+ context "when missing client_id" do
179
+ before do
180
+ allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
149
181
 
150
- post :create, params: {
151
- client_id: client.uid,
152
- response_type: "token",
153
- scope: "invalid",
154
- redirect_uri: client.redirect_uri,
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
- let(:response_json_body) { JSON.parse(response.body) }
159
- let(:redirect_uri) { response_json_body["redirect_uri"] }
189
+ let(:response_json_body) { JSON.parse(response.body) }
160
190
 
161
- it "renders 400 error" do
162
- expect(response.status).to eq 400
163
- end
191
+ it "renders 400 error" do
192
+ expect(response.status).to eq 400
193
+ end
164
194
 
165
- it "includes correct redirect URI" do
166
- expect(redirect_uri).to match(/^#{client.redirect_uri}/)
167
- end
195
+ it "includes error name" do
196
+ expect(response_json_body["error"]).to eq("invalid_request")
197
+ end
168
198
 
169
- it "does not include access token in fragment" do
170
- expect(redirect_uri.match(/access_token=([a-f0-9]+)&?/)).to be_nil
171
- end
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
- it "includes error in redirect uri" do
174
- expect(redirect_uri.match(/error=([a-z_]+)&?/)[1]).to eq "invalid_scope"
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
- it "includes error description in redirect uri" do
178
- expect(redirect_uri.match(/error_description=(.+)&?/)[1]).to_not be_nil
179
- end
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
- it "does not issue any access token" do
182
- expect(Doorkeeper::AccessToken.all).to be_empty
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("unsupported_response_type")
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(translated_error_message(:unsupported_response_type))
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 match(/application\/json/)
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 match(/text\/plain/)
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 match(/application\/json/)
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
- describe "when authorization has succeeded" do
7
- let(:token) { double(:token, authorize: true) }
6
+ let(:client) { FactoryBot.create :application }
7
+ let!(:user) { User.create!(name: "Joe", password: "sekret") }
8
8
 
9
- it "returns the authorization" do
10
- skip "verify need of these specs"
9
+ before do
10
+ Doorkeeper.configure do
11
+ resource_owner_from_credentials do
12
+ User.first
13
+ end
14
+ end
11
15
 
12
- expect(token).to receive(:authorization)
16
+ allow(Doorkeeper.configuration).to receive(:grant_flows).and_return(["password"])
17
+ end
13
18
 
14
- post :create
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 "when authorization has failed" do
19
- it "returns the error response" do
20
- token = double(:token, authorize: false)
21
- allow(controller).to receive(:token) { token }
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
- post :create
64
+ it "responds after authorization" do
65
+ expect(response).to be_unauthorized
66
+ end
24
67
 
25
- expect(response.status).to eq 400
26
- expect(response.headers["WWW-Authenticate"]).to match(/Bearer/)
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 "when there is a failure due to a custom error" do
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 "revoking tokens" do
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 200" do
213
+ it "returns 403" do
106
214
  post :revoke, params: { token: access_token.token }
107
215
 
108
- expect(response.status).to eq 200
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 "authorize response memoization" do
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 valid Client Authentication" do
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 invalid token error" do
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 only active state" do
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
- should_have_json "active", false
281
- expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
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