doorkeeper 5.4.0.rc1 → 5.5.0

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 (219) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +108 -9
  3. data/README.md +4 -4
  4. data/app/controllers/doorkeeper/applications_controller.rb +3 -3
  5. data/app/controllers/doorkeeper/authorizations_controller.rb +16 -5
  6. data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
  7. data/app/controllers/doorkeeper/token_info_controller.rb +12 -2
  8. data/app/controllers/doorkeeper/tokens_controller.rb +34 -26
  9. data/app/views/doorkeeper/applications/_form.html.erb +1 -1
  10. data/app/views/doorkeeper/applications/show.html.erb +16 -12
  11. data/app/views/doorkeeper/authorizations/form_post.html.erb +11 -0
  12. data/config/locales/en.yml +3 -1
  13. data/lib/doorkeeper.rb +6 -1
  14. data/lib/doorkeeper/config.rb +109 -78
  15. data/lib/doorkeeper/config/abstract_builder.rb +1 -1
  16. data/lib/doorkeeper/config/option.rb +1 -3
  17. data/lib/doorkeeper/config/validations.rb +53 -0
  18. data/lib/doorkeeper/engine.rb +1 -1
  19. data/lib/doorkeeper/grant_flow.rb +45 -0
  20. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  21. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  22. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  23. data/lib/doorkeeper/helpers/controller.rb +8 -4
  24. data/lib/doorkeeper/models/access_grant_mixin.rb +12 -7
  25. data/lib/doorkeeper/models/access_token_mixin.rb +12 -8
  26. data/lib/doorkeeper/models/application_mixin.rb +5 -4
  27. data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
  28. data/lib/doorkeeper/oauth/authorization/code.rb +5 -1
  29. data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
  30. data/lib/doorkeeper/oauth/authorization/token.rb +11 -5
  31. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +1 -1
  32. data/lib/doorkeeper/oauth/authorization_code_request.rb +10 -17
  33. data/lib/doorkeeper/oauth/base_request.rb +1 -1
  34. data/lib/doorkeeper/oauth/client_credentials/creator.rb +3 -2
  35. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +1 -0
  36. data/lib/doorkeeper/oauth/client_credentials/validator.rb +3 -1
  37. data/lib/doorkeeper/oauth/code_request.rb +2 -2
  38. data/lib/doorkeeper/oauth/code_response.rb +17 -11
  39. data/lib/doorkeeper/oauth/error_response.rb +4 -3
  40. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -3
  41. data/lib/doorkeeper/oauth/password_access_token_request.rb +21 -2
  42. data/lib/doorkeeper/oauth/pre_authorization.rb +37 -11
  43. data/lib/doorkeeper/oauth/refresh_token_request.rb +13 -0
  44. data/lib/doorkeeper/oauth/token.rb +4 -5
  45. data/lib/doorkeeper/oauth/token_introspection.rb +1 -5
  46. data/lib/doorkeeper/oauth/token_request.rb +1 -1
  47. data/lib/doorkeeper/orm/active_record.rb +5 -6
  48. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +12 -2
  49. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +10 -2
  50. data/lib/doorkeeper/orm/active_record/mixins/application.rb +76 -10
  51. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +5 -0
  52. data/lib/doorkeeper/rails/routes.rb +1 -3
  53. data/lib/doorkeeper/rake/db.rake +3 -3
  54. data/lib/doorkeeper/rake/setup.rake +5 -0
  55. data/lib/doorkeeper/request.rb +49 -12
  56. data/lib/doorkeeper/request/refresh_token.rb +2 -1
  57. data/lib/doorkeeper/server.rb +1 -1
  58. data/lib/doorkeeper/stale_records_cleaner.rb +4 -4
  59. data/lib/doorkeeper/version.rb +2 -6
  60. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +1 -1
  61. data/lib/generators/doorkeeper/templates/initializer.rb +9 -7
  62. data/lib/generators/doorkeeper/templates/migration.rb.erb +12 -5
  63. metadata +25 -306
  64. data/Appraisals +0 -26
  65. data/CODE_OF_CONDUCT.md +0 -46
  66. data/CONTRIBUTING.md +0 -49
  67. data/Dangerfile +0 -67
  68. data/Dockerfile +0 -29
  69. data/Gemfile +0 -25
  70. data/NEWS.md +0 -1
  71. data/RELEASING.md +0 -11
  72. data/Rakefile +0 -28
  73. data/SECURITY.md +0 -15
  74. data/UPGRADE.md +0 -2
  75. data/bin/console +0 -30
  76. data/doorkeeper.gemspec +0 -42
  77. data/gemfiles/rails_5_0.gemfile +0 -19
  78. data/gemfiles/rails_5_1.gemfile +0 -19
  79. data/gemfiles/rails_5_2.gemfile +0 -19
  80. data/gemfiles/rails_6_0.gemfile +0 -19
  81. data/gemfiles/rails_master.gemfile +0 -19
  82. data/spec/controllers/application_metal_controller_spec.rb +0 -64
  83. data/spec/controllers/applications_controller_spec.rb +0 -274
  84. data/spec/controllers/authorizations_controller_spec.rb +0 -743
  85. data/spec/controllers/protected_resources_controller_spec.rb +0 -361
  86. data/spec/controllers/token_info_controller_spec.rb +0 -50
  87. data/spec/controllers/tokens_controller_spec.rb +0 -499
  88. data/spec/dummy/Rakefile +0 -9
  89. data/spec/dummy/app/assets/config/manifest.js +0 -2
  90. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  91. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
  92. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
  93. data/spec/dummy/app/controllers/home_controller.rb +0 -18
  94. data/spec/dummy/app/controllers/metal_controller.rb +0 -13
  95. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
  96. data/spec/dummy/app/helpers/application_helper.rb +0 -7
  97. data/spec/dummy/app/models/user.rb +0 -11
  98. data/spec/dummy/app/views/home/index.html.erb +0 -0
  99. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  100. data/spec/dummy/config.ru +0 -6
  101. data/spec/dummy/config/application.rb +0 -51
  102. data/spec/dummy/config/boot.rb +0 -7
  103. data/spec/dummy/config/database.yml +0 -15
  104. data/spec/dummy/config/environment.rb +0 -5
  105. data/spec/dummy/config/environments/development.rb +0 -31
  106. data/spec/dummy/config/environments/production.rb +0 -64
  107. data/spec/dummy/config/environments/test.rb +0 -45
  108. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
  109. data/spec/dummy/config/initializers/doorkeeper.rb +0 -166
  110. data/spec/dummy/config/initializers/secret_token.rb +0 -10
  111. data/spec/dummy/config/initializers/session_store.rb +0 -10
  112. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  113. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  114. data/spec/dummy/config/routes.rb +0 -13
  115. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  116. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  117. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
  118. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  119. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  120. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
  121. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
  122. data/spec/dummy/db/schema.rb +0 -70
  123. data/spec/dummy/public/404.html +0 -26
  124. data/spec/dummy/public/422.html +0 -26
  125. data/spec/dummy/public/500.html +0 -26
  126. data/spec/dummy/public/favicon.ico +0 -0
  127. data/spec/dummy/script/rails +0 -9
  128. data/spec/factories.rb +0 -30
  129. data/spec/generators/application_owner_generator_spec.rb +0 -28
  130. data/spec/generators/confidential_applications_generator_spec.rb +0 -29
  131. data/spec/generators/enable_polymorphic_resource_owner_generator_spec.rb +0 -47
  132. data/spec/generators/install_generator_spec.rb +0 -36
  133. data/spec/generators/migration_generator_spec.rb +0 -28
  134. data/spec/generators/pkce_generator_spec.rb +0 -28
  135. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
  136. data/spec/generators/templates/routes.rb +0 -4
  137. data/spec/generators/views_generator_spec.rb +0 -29
  138. data/spec/grape/grape_integration_spec.rb +0 -137
  139. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
  140. data/spec/lib/config_spec.rb +0 -813
  141. data/spec/lib/doorkeeper_spec.rb +0 -27
  142. data/spec/lib/models/expirable_spec.rb +0 -61
  143. data/spec/lib/models/reusable_spec.rb +0 -40
  144. data/spec/lib/models/revocable_spec.rb +0 -58
  145. data/spec/lib/models/scopes_spec.rb +0 -61
  146. data/spec/lib/models/secret_storable_spec.rb +0 -135
  147. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
  148. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -180
  149. data/spec/lib/oauth/base_request_spec.rb +0 -210
  150. data/spec/lib/oauth/base_response_spec.rb +0 -45
  151. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  152. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -135
  153. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -110
  154. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -57
  155. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
  156. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -108
  157. data/spec/lib/oauth/client_spec.rb +0 -38
  158. data/spec/lib/oauth/code_request_spec.rb +0 -46
  159. data/spec/lib/oauth/code_response_spec.rb +0 -36
  160. data/spec/lib/oauth/error_response_spec.rb +0 -64
  161. data/spec/lib/oauth/error_spec.rb +0 -21
  162. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -20
  163. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -110
  164. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
  165. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -262
  166. data/spec/lib/oauth/invalid_request_response_spec.rb +0 -73
  167. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -53
  168. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -201
  169. data/spec/lib/oauth/pre_authorization_spec.rb +0 -218
  170. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -166
  171. data/spec/lib/oauth/scopes_spec.rb +0 -146
  172. data/spec/lib/oauth/token_request_spec.rb +0 -164
  173. data/spec/lib/oauth/token_response_spec.rb +0 -84
  174. data/spec/lib/oauth/token_spec.rb +0 -156
  175. data/spec/lib/option_spec.rb +0 -51
  176. data/spec/lib/request/strategy_spec.rb +0 -54
  177. data/spec/lib/secret_storing/base_spec.rb +0 -60
  178. data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
  179. data/spec/lib/secret_storing/plain_spec.rb +0 -44
  180. data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
  181. data/spec/lib/server_spec.rb +0 -49
  182. data/spec/lib/stale_records_cleaner_spec.rb +0 -102
  183. data/spec/models/doorkeeper/access_grant_spec.rb +0 -175
  184. data/spec/models/doorkeeper/access_token_spec.rb +0 -650
  185. data/spec/models/doorkeeper/application_spec.rb +0 -442
  186. data/spec/requests/applications/applications_request_spec.rb +0 -259
  187. data/spec/requests/applications/authorized_applications_spec.rb +0 -32
  188. data/spec/requests/endpoints/authorization_spec.rb +0 -91
  189. data/spec/requests/endpoints/token_spec.rb +0 -79
  190. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -82
  191. data/spec/requests/flows/authorization_code_spec.rb +0 -530
  192. data/spec/requests/flows/client_credentials_spec.rb +0 -207
  193. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -46
  194. data/spec/requests/flows/implicit_grant_spec.rb +0 -91
  195. data/spec/requests/flows/password_spec.rb +0 -316
  196. data/spec/requests/flows/refresh_token_spec.rb +0 -241
  197. data/spec/requests/flows/revoke_token_spec.rb +0 -196
  198. data/spec/requests/flows/skip_authorization_spec.rb +0 -66
  199. data/spec/requests/protected_resources/metal_spec.rb +0 -16
  200. data/spec/requests/protected_resources/private_api_spec.rb +0 -83
  201. data/spec/routing/custom_controller_routes_spec.rb +0 -133
  202. data/spec/routing/default_routes_spec.rb +0 -41
  203. data/spec/routing/scoped_routes_spec.rb +0 -47
  204. data/spec/spec_helper.rb +0 -54
  205. data/spec/spec_helper_integration.rb +0 -4
  206. data/spec/support/dependencies/factory_bot.rb +0 -4
  207. data/spec/support/doorkeeper_rspec.rb +0 -22
  208. data/spec/support/helpers/access_token_request_helper.rb +0 -14
  209. data/spec/support/helpers/authorization_request_helper.rb +0 -43
  210. data/spec/support/helpers/config_helper.rb +0 -11
  211. data/spec/support/helpers/model_helper.rb +0 -78
  212. data/spec/support/helpers/request_spec_helper.rb +0 -110
  213. data/spec/support/helpers/url_helper.rb +0 -62
  214. data/spec/support/orm/active_record.rb +0 -5
  215. data/spec/support/shared/controllers_shared_context.rb +0 -133
  216. data/spec/support/shared/hashing_shared_context.rb +0 -36
  217. data/spec/support/shared/models_shared_examples.rb +0 -56
  218. data/spec/validators/redirect_uri_validator_spec.rb +0 -183
  219. data/spec/version/version_spec.rb +0 -17
@@ -1,361 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- module ControllerActions
6
- def index
7
- render plain: "index"
8
- end
9
-
10
- def show
11
- render plain: "show"
12
- end
13
-
14
- def doorkeeper_unauthorized_render_options(*); end
15
-
16
- def doorkeeper_forbidden_render_options(*); end
17
- end
18
-
19
- describe "doorkeeper authorize filter" do
20
- context "accepts token code specified as" do
21
- controller do
22
- before_action :doorkeeper_authorize!
23
-
24
- def index
25
- render plain: "index"
26
- end
27
- end
28
-
29
- let(:token_string) { "1A2BC3" }
30
- let(:token) do
31
- double(
32
- Doorkeeper::AccessToken,
33
- acceptable?: true, previous_refresh_token: "",
34
- revoke_previous_refresh_token!: true,
35
- )
36
- end
37
-
38
- it "access_token param" do
39
- expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
40
- get :index, params: { access_token: token_string }
41
- end
42
-
43
- it "bearer_token param" do
44
- expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
45
- get :index, params: { bearer_token: token_string }
46
- end
47
-
48
- it "Authorization header" do
49
- expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
50
- request.env["HTTP_AUTHORIZATION"] = "Bearer #{token_string}"
51
- get :index
52
- end
53
-
54
- it "different kind of Authorization header" do
55
- expect(Doorkeeper::AccessToken).not_to receive(:by_token)
56
- request.env["HTTP_AUTHORIZATION"] = "MAC #{token_string}"
57
- get :index
58
- end
59
-
60
- it "does not change Authorization header value" do
61
- expect(Doorkeeper::AccessToken).to receive(:by_token).exactly(2).times.and_return(token)
62
- request.env["HTTP_AUTHORIZATION"] = "Bearer #{token_string}"
63
- get :index
64
- controller.send(:remove_instance_variable, :@doorkeeper_token)
65
- get :index
66
- end
67
- end
68
-
69
- context "defined for all actions" do
70
- controller do
71
- before_action :doorkeeper_authorize!
72
-
73
- include ControllerActions
74
- end
75
-
76
- context "with valid token", token: :valid do
77
- it "allows into index action" do
78
- get :index, params: { access_token: token_string }
79
- expect(response).to be_successful
80
- end
81
-
82
- it "allows into show action" do
83
- get :show, params: { id: "4", access_token: token_string }
84
- expect(response).to be_successful
85
- end
86
- end
87
-
88
- context "with invalid token", token: :invalid do
89
- it "does not allow into index action" do
90
- get :index, params: { access_token: token_string }
91
- expect(response.status).to eq 401
92
- expect(response.header["WWW-Authenticate"]).to match(/^Bearer/)
93
- end
94
-
95
- it "does not allow into show action" do
96
- get :show, params: { id: "4", access_token: token_string }
97
- expect(response.status).to eq 401
98
- expect(response.header["WWW-Authenticate"]).to match(/^Bearer/)
99
- end
100
- end
101
- end
102
-
103
- context "defined with scopes" do
104
- controller do
105
- before_action -> { doorkeeper_authorize! :write }
106
-
107
- include ControllerActions
108
- end
109
-
110
- let(:token_string) { "1A2DUWE" }
111
-
112
- it "allows if the token has particular scopes" do
113
- token = double(
114
- Doorkeeper::AccessToken,
115
- accessible?: true, scopes: %w[write public],
116
- previous_refresh_token: "",
117
- revoke_previous_refresh_token!: true,
118
- )
119
- expect(token).to receive(:acceptable?).with([:write]).and_return(true)
120
- expect(
121
- Doorkeeper::AccessToken,
122
- ).to receive(:by_token).with(token_string).and_return(token)
123
-
124
- get :index, params: { access_token: token_string }
125
- expect(response).to be_successful
126
- end
127
-
128
- it "does not allow if the token does not include given scope" do
129
- token = double(
130
- Doorkeeper::AccessToken,
131
- accessible?: true, scopes: ["public"], revoked?: false,
132
- expired?: false, previous_refresh_token: "",
133
- revoke_previous_refresh_token!: true,
134
- )
135
- expect(
136
- Doorkeeper::AccessToken,
137
- ).to receive(:by_token).with(token_string).and_return(token)
138
- expect(token).to receive(:acceptable?).with([:write]).and_return(false)
139
-
140
- get :index, params: { access_token: token_string }
141
- expect(response.status).to eq 403
142
- expect(response.header).to_not include("WWW-Authenticate")
143
- end
144
- end
145
-
146
- context "when custom unauthorized render options are configured" do
147
- controller do
148
- before_action :doorkeeper_authorize!
149
-
150
- include ControllerActions
151
- end
152
-
153
- context "with a JSON custom render", token: :invalid do
154
- before do
155
- module ControllerActions
156
- remove_method :doorkeeper_unauthorized_render_options
157
-
158
- def doorkeeper_unauthorized_render_options(error: nil)
159
- { json: ActiveSupport::JSON.encode(error_message: error.description) }
160
- end
161
- end
162
- end
163
-
164
- after do
165
- module ControllerActions
166
- remove_method :doorkeeper_unauthorized_render_options
167
-
168
- def doorkeeper_unauthorized_render_options(error: nil); end
169
- end
170
- end
171
-
172
- it "it renders a custom JSON response", token: :invalid do
173
- get :index, params: { access_token: token_string }
174
- expect(response.status).to eq 401
175
- expect(response.content_type).to include("application/json")
176
- expect(response.header["WWW-Authenticate"]).to match(/^Bearer/)
177
-
178
- expect(json_response).not_to be_nil
179
- expect(json_response["error_message"]).to match("token is invalid")
180
- end
181
- end
182
-
183
- context "with a text custom render", token: :invalid do
184
- before do
185
- module ControllerActions
186
- remove_method :doorkeeper_unauthorized_render_options
187
-
188
- def doorkeeper_unauthorized_render_options(**)
189
- { plain: "Unauthorized" }
190
- end
191
- end
192
- end
193
-
194
- after do
195
- module ControllerActions
196
- remove_method :doorkeeper_unauthorized_render_options
197
-
198
- def doorkeeper_unauthorized_render_options(error: nil); end
199
- end
200
- end
201
-
202
- it "it renders a custom text response", token: :invalid do
203
- get :index, params: { access_token: token_string }
204
- expect(response.status).to eq 401
205
- expect(response.content_type).to include("text/plain")
206
- expect(response.header["WWW-Authenticate"]).to match(/^Bearer/)
207
- expect(response.body).to eq("Unauthorized")
208
- end
209
- end
210
- end
211
-
212
- context "when custom forbidden render options are configured" do
213
- before do
214
- expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
215
- expect(token).to receive(:acceptable?).with([:write]).and_return(false)
216
- end
217
-
218
- after do
219
- module ControllerActions
220
- remove_method :doorkeeper_forbidden_render_options
221
-
222
- def doorkeeper_forbidden_render_options(*); end
223
- end
224
- end
225
-
226
- controller do
227
- before_action -> { doorkeeper_authorize! :write }
228
-
229
- include ControllerActions
230
- end
231
-
232
- let(:token) do
233
- double(
234
- Doorkeeper::AccessToken,
235
- accessible?: true, scopes: ["public"], revoked?: false,
236
- expired?: false, previous_refresh_token: "",
237
- revoke_previous_refresh_token!: true,
238
- )
239
- end
240
-
241
- let(:token_string) { "1A2DUWE" }
242
-
243
- context "with a JSON custom render" do
244
- before do
245
- module ControllerActions
246
- remove_method :doorkeeper_forbidden_render_options
247
-
248
- def doorkeeper_forbidden_render_options(*)
249
- { json: { error_message: "Forbidden" } }
250
- end
251
- end
252
- end
253
-
254
- it "renders a custom JSON response" do
255
- get :index, params: { access_token: token_string }
256
- expect(response.header).to_not include("WWW-Authenticate")
257
- expect(response.content_type).to include("application/json")
258
- expect(response.status).to eq 403
259
-
260
- expect(json_response).not_to be_nil
261
- expect(json_response["error_message"]).to match("Forbidden")
262
- end
263
- end
264
-
265
- context "with a status and JSON custom render" do
266
- before do
267
- module ControllerActions
268
- remove_method :doorkeeper_forbidden_render_options
269
- def doorkeeper_forbidden_render_options(*)
270
- { json: { error_message: "Not Found" },
271
- respond_not_found_when_forbidden: true, }
272
- end
273
- end
274
- end
275
-
276
- it "overrides the default status code" do
277
- get :index, params: { access_token: token_string }
278
- expect(response.status).to eq 404
279
- end
280
- end
281
-
282
- context "with a text custom render" do
283
- before do
284
- module ControllerActions
285
- remove_method :doorkeeper_forbidden_render_options
286
-
287
- def doorkeeper_forbidden_render_options(*)
288
- { plain: "Forbidden" }
289
- end
290
- end
291
- end
292
-
293
- it "renders a custom status code and text response" do
294
- get :index, params: { access_token: token_string }
295
- expect(response.header).to_not include("WWW-Authenticate")
296
- expect(response.status).to eq 403
297
- expect(response.body).to eq("Forbidden")
298
- end
299
- end
300
-
301
- context "with a status and text custom render" do
302
- before do
303
- module ControllerActions
304
- remove_method :doorkeeper_forbidden_render_options
305
-
306
- def doorkeeper_forbidden_render_options(*)
307
- { respond_not_found_when_forbidden: true, plain: "Not Found" }
308
- end
309
- end
310
- end
311
-
312
- it "overrides the default status code" do
313
- get :index, params: { access_token: token_string }
314
- expect(response.status).to eq 404
315
- end
316
- end
317
- end
318
-
319
- context "when handle_auth_errors option is set to :raise" do
320
- subject { get :index, params: { access_token: token_string } }
321
-
322
- before do
323
- config_is_set(:handle_auth_errors, :raise)
324
- end
325
-
326
- controller do
327
- before_action :doorkeeper_authorize!
328
- include ControllerActions
329
- end
330
-
331
- context "when token is unknown" do
332
- it "raises Doorkeeper::Errors::TokenUnknown exception", token: :invalid do
333
- expect { subject }.to raise_error(Doorkeeper::Errors::TokenUnknown)
334
- end
335
- end
336
-
337
- context "when token is expired" do
338
- it "raises Doorkeeper::Errors::TokenExpired exception", token: :expired do
339
- expect { subject }.to raise_error(Doorkeeper::Errors::TokenExpired)
340
- end
341
- end
342
-
343
- context "when token is revoked" do
344
- it "raises Doorkeeper::Errors::TokenRevoked exception", token: :revoked do
345
- expect { subject }.to raise_error(Doorkeeper::Errors::TokenRevoked)
346
- end
347
- end
348
-
349
- context "when token is forbidden" do
350
- it "raises Doorkeeper::Errors::TokenForbidden exception", token: :forbidden do
351
- expect { subject }.to raise_error(Doorkeeper::Errors::TokenForbidden)
352
- end
353
- end
354
-
355
- context "when token is valid" do
356
- it "allows into index action", token: :valid do
357
- expect(response).to be_successful
358
- end
359
- end
360
- end
361
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- describe Doorkeeper::TokenInfoController do
6
- describe "when requesting token info with valid token" do
7
- let(:doorkeeper_token) { FactoryBot.create(:access_token) }
8
-
9
- describe "successful request" do
10
- it "responds with token info" do
11
- get :show, params: { access_token: doorkeeper_token.token }
12
-
13
- expect(response.body).to eq(doorkeeper_token.to_json)
14
- end
15
-
16
- it "responds with a 200 status" do
17
- get :show, params: { access_token: doorkeeper_token.token }
18
-
19
- expect(response.status).to eq 200
20
- end
21
- end
22
-
23
- describe "invalid token response" do
24
- it "responds with 401 when doorkeeper_token is not valid" do
25
- get :show
26
-
27
- expect(response.status).to eq 401
28
- expect(response.headers["WWW-Authenticate"]).to match(/^Bearer/)
29
- end
30
-
31
- it "responds with 401 when doorkeeper_token is invalid, expired or revoked" do
32
- allow(controller).to receive(:doorkeeper_token).and_return(doorkeeper_token)
33
- allow(doorkeeper_token).to receive(:accessible?).and_return(false)
34
-
35
- get :show
36
-
37
- expect(response.status).to eq 401
38
- expect(response.headers["WWW-Authenticate"]).to match(/^Bearer/)
39
- end
40
-
41
- it "responds body message for error" do
42
- get :show
43
-
44
- expect(response.body).to eq(
45
- Doorkeeper::OAuth::InvalidTokenResponse.new.body.to_json,
46
- )
47
- end
48
- end
49
- end
50
- end
@@ -1,499 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- describe Doorkeeper::TokensController do
6
- let(:client) { FactoryBot.create :application }
7
- let!(:user) { User.create!(name: "Joe", password: "sekret") }
8
-
9
- before do
10
- Doorkeeper.configure do
11
- resource_owner_from_credentials do
12
- User.first
13
- end
14
- end
15
-
16
- allow(Doorkeeper.configuration).to receive(:grant_flows).and_return(["password"])
17
- end
18
-
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)
52
- end
53
- end
54
-
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
63
-
64
- it "responds after authorization" do
65
- expect(response).to be_unauthorized
66
- end
67
-
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), nil)
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)
115
- .with(instance_of(described_class), instance_of(Doorkeeper::OAuth::Hooks::Context))
116
- end
117
- end
118
-
119
- describe "with errors" do
120
- after do
121
- post :create, params: {
122
- client_id: client.uid,
123
- client_secret: "invalid",
124
- grant_type: "password",
125
- }
126
- end
127
-
128
- it "should call :before_successful_authorization callback" do
129
- expect(Doorkeeper.configuration)
130
- .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class), nil)
131
- end
132
-
133
- it "should not call :after_successful_authorization callback" do
134
- expect(Doorkeeper.configuration).not_to receive(:after_successful_authorization)
135
- end
136
- end
137
- end
138
-
139
- describe "POST #create with custom error" do
140
- it "returns the error response with a custom message" do
141
- # I18n looks for `doorkeeper.errors.messages.custom_message` in locale files
142
- custom_message = "my_message"
143
- allow(I18n).to receive(:translate)
144
- .with(
145
- custom_message,
146
- hash_including(scope: %i[doorkeeper errors messages]),
147
- )
148
- .and_return("Authorization custom message")
149
-
150
- doorkeeper_error = Doorkeeper::Errors::DoorkeeperError.new(custom_message)
151
-
152
- strategy = double(:strategy)
153
- request = double(token_request: strategy)
154
- allow(strategy).to receive(:authorize).and_raise(doorkeeper_error)
155
- allow(controller).to receive(:server).and_return(request)
156
-
157
- post :create
158
-
159
- expected_response_body = {
160
- "error" => custom_message,
161
- "error_description" => "Authorization custom message",
162
- }
163
- expect(response.status).to eq 400
164
- expect(response.headers["WWW-Authenticate"]).to match(/Bearer/)
165
- expect(JSON.parse(response.body)).to eq expected_response_body
166
- end
167
- end
168
-
169
- # http://tools.ietf.org/html/rfc7009#section-2.2
170
- describe "POST #revoke" do
171
- let(:client) { FactoryBot.create(:application) }
172
- let(:access_token) { FactoryBot.create(:access_token, application: client) }
173
-
174
- context "when associated app is public" do
175
- let(:client) { FactoryBot.create(:application, confidential: false) }
176
-
177
- it "returns 200" do
178
- post :revoke, params: { client_id: client.uid, token: access_token.token }
179
-
180
- expect(response.status).to eq 200
181
- end
182
-
183
- it "revokes the access token" do
184
- post :revoke, params: { client_id: client.uid, token: access_token.token }
185
-
186
- expect(access_token.reload).to have_attributes(revoked?: true)
187
- end
188
- end
189
-
190
- context "when associated app is confidential" do
191
- let(:client) { FactoryBot.create(:application, confidential: true) }
192
- let(:oauth_client) { Doorkeeper::OAuth::Client.new(client) }
193
-
194
- before(:each) do
195
- allow_any_instance_of(Doorkeeper::Server).to receive(:client) { oauth_client }
196
- end
197
-
198
- it "returns 200" do
199
- post :revoke, params: { token: access_token.token }
200
-
201
- expect(response.status).to eq 200
202
- end
203
-
204
- it "revokes the access token" do
205
- post :revoke, params: { token: access_token.token }
206
-
207
- expect(access_token.reload).to have_attributes(revoked?: true)
208
- end
209
-
210
- context "when authorization fails" do
211
- let(:some_other_client) { FactoryBot.create(:application, confidential: true) }
212
- let(:oauth_client) { Doorkeeper::OAuth::Client.new(some_other_client) }
213
-
214
- it "returns 403" do
215
- post :revoke, params: { token: access_token.token }
216
-
217
- expect(response.status).to eq 403
218
- end
219
-
220
- it "does not revoke the access token" do
221
- post :revoke, params: { token: access_token.token }
222
-
223
- expect(access_token.reload).to have_attributes(revoked?: false)
224
- end
225
- end
226
- end
227
- end
228
-
229
- describe "POST #introspect" do
230
- let(:client) { FactoryBot.create(:application) }
231
- let(:access_token) { FactoryBot.create(:access_token, application: client) }
232
- let(:token_for_introspection) { FactoryBot.create(:access_token, application: client) }
233
-
234
- context "authorized using valid Bearer token" do
235
- it "responds with full token introspection" do
236
- request.headers["Authorization"] = "Bearer #{access_token.token}"
237
-
238
- post :introspect, params: { token: token_for_introspection.token }
239
-
240
- should_have_json "active", true
241
- expect(json_response).to include("client_id", "token_type", "exp", "iat")
242
- end
243
- end
244
-
245
- context "authorized using Client Credentials of the client that token is issued to" do
246
- it "responds with full token introspection" do
247
- request.headers["Authorization"] = basic_auth_header_for_client(client)
248
-
249
- post :introspect, params: { token: token_for_introspection.token }
250
-
251
- should_have_json "active", true
252
- expect(json_response).to include("client_id", "token_type", "exp", "iat")
253
- should_have_json "client_id", client.uid
254
- end
255
- end
256
-
257
- context "configured token introspection disabled" do
258
- before do
259
- Doorkeeper.configure do
260
- orm DOORKEEPER_ORM
261
- allow_token_introspection false
262
- end
263
- end
264
-
265
- it "responds with invalid_token error" do
266
- request.headers["Authorization"] = "Bearer #{access_token.token}"
267
-
268
- post :introspect, params: { token: token_for_introspection.token }
269
-
270
- response_status_should_be 401
271
-
272
- should_not_have_json "active"
273
- should_have_json "error", "invalid_token"
274
- end
275
- end
276
-
277
- context "using custom introspection response" do
278
- before do
279
- Doorkeeper.configure do
280
- orm DOORKEEPER_ORM
281
- custom_introspection_response do |_token, _context|
282
- {
283
- sub: "Z5O3upPC88QrAjx00dis",
284
- aud: "https://protected.example.net/resource",
285
- }
286
- end
287
- end
288
- end
289
-
290
- it "responds with full token introspection" do
291
- request.headers["Authorization"] = "Bearer #{access_token.token}"
292
-
293
- post :introspect, params: { token: token_for_introspection.token }
294
-
295
- expect(json_response).to include("client_id", "token_type", "exp", "iat", "sub", "aud")
296
- should_have_json "sub", "Z5O3upPC88QrAjx00dis"
297
- should_have_json "aud", "https://protected.example.net/resource"
298
- end
299
- end
300
-
301
- context "public access token" do
302
- let(:token_for_introspection) { FactoryBot.create(:access_token, application: nil) }
303
-
304
- it "responds with full token introspection" do
305
- request.headers["Authorization"] = basic_auth_header_for_client(client)
306
-
307
- post :introspect, params: { token: token_for_introspection.token }
308
-
309
- should_have_json "active", true
310
- expect(json_response).to include("client_id", "token_type", "exp", "iat")
311
- should_have_json "client_id", nil
312
- end
313
- end
314
-
315
- context "token was issued to a different client than is making this request" do
316
- let(:different_client) { FactoryBot.create(:application) }
317
-
318
- it "responds with only active state" do
319
- request.headers["Authorization"] = basic_auth_header_for_client(different_client)
320
-
321
- post :introspect, params: { token: token_for_introspection.token }
322
-
323
- expect(response).to be_successful
324
-
325
- should_have_json "active", false
326
- expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
327
- end
328
- end
329
-
330
- context "introspection request authorized by a client and allow_token_introspection is true" do
331
- let(:different_client) { FactoryBot.create(:application) }
332
-
333
- before do
334
- allow(Doorkeeper.configuration).to receive(:allow_token_introspection).and_return(proc do
335
- true
336
- end)
337
- end
338
-
339
- it "responds with full token introspection" do
340
- request.headers["Authorization"] = basic_auth_header_for_client(different_client)
341
-
342
- post :introspect, params: { token: token_for_introspection.token }
343
-
344
- should_have_json "active", true
345
- expect(json_response).to include("client_id", "token_type", "exp", "iat")
346
- should_have_json "client_id", client.uid
347
- end
348
- end
349
-
350
- context "allow_token_introspection requires authorized token with special scope" do
351
- let(:access_token) { FactoryBot.create(:access_token, scopes: "introspection") }
352
-
353
- before do
354
- allow(Doorkeeper.configuration).to receive(:allow_token_introspection).and_return(proc do |_token, _client, authorized_token|
355
- authorized_token.scopes.include?("introspection")
356
- end)
357
- end
358
-
359
- it "responds with full token introspection if authorized token has introspection scope" do
360
- request.headers["Authorization"] = "Bearer #{access_token.token}"
361
-
362
- post :introspect, params: { token: token_for_introspection.token }
363
-
364
- should_have_json "active", true
365
- expect(json_response).to include("client_id", "token_type", "exp", "iat")
366
- end
367
-
368
- it "responds with invalid_token error if authorized token doesn't have introspection scope" do
369
- access_token.update(scopes: "read write")
370
-
371
- request.headers["Authorization"] = "Bearer #{access_token.token}"
372
-
373
- post :introspect, params: { token: token_for_introspection.token }
374
-
375
- response_status_should_be 401
376
-
377
- should_not_have_json "active"
378
- should_have_json "error", "invalid_token"
379
- end
380
- end
381
-
382
- context "authorized using invalid Bearer token" do
383
- let(:access_token) do
384
- FactoryBot.create(:access_token, application: client, revoked_at: 1.day.ago)
385
- end
386
-
387
- it "responds with invalid_token error" do
388
- request.headers["Authorization"] = "Bearer #{access_token.token}"
389
-
390
- post :introspect, params: { token: token_for_introspection.token }
391
-
392
- response_status_should_be 401
393
-
394
- should_not_have_json "active"
395
- should_have_json "error", "invalid_token"
396
- end
397
- end
398
-
399
- context "authorized using the Bearer token that need to be introspected" do
400
- it "responds with invalid token error" do
401
- request.headers["Authorization"] = "Bearer #{access_token.token}"
402
-
403
- post :introspect, params: { token: access_token.token }
404
-
405
- response_status_should_be 401
406
-
407
- should_not_have_json "active"
408
- should_have_json "error", "invalid_token"
409
- end
410
- end
411
-
412
- context "using invalid credentials to authorize" do
413
- let(:client) { double(uid: "123123", secret: "666999") }
414
- let(:access_token) { FactoryBot.create(:access_token) }
415
-
416
- it "responds with invalid_client error" do
417
- request.headers["Authorization"] = basic_auth_header_for_client(client)
418
-
419
- post :introspect, params: { token: access_token.token }
420
-
421
- expect(response).not_to be_successful
422
- response_status_should_be 401
423
-
424
- should_not_have_json "active"
425
- should_have_json "error", "invalid_client"
426
- end
427
- end
428
-
429
- context "using wrong token value" do
430
- context "authorized using client credentials" do
431
- it "responds with only active state" do
432
- request.headers["Authorization"] = basic_auth_header_for_client(client)
433
-
434
- post :introspect, params: { token: SecureRandom.hex(16) }
435
-
436
- should_have_json "active", false
437
- expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
438
- end
439
- end
440
-
441
- context "authorized using valid Bearer token" do
442
- it "responds with invalid_token error" do
443
- request.headers["Authorization"] = "Bearer #{access_token.token}"
444
-
445
- post :introspect, params: { token: SecureRandom.hex(16) }
446
-
447
- response_status_should_be 401
448
-
449
- should_not_have_json "active"
450
- should_have_json "error", "invalid_token"
451
- end
452
- end
453
- end
454
-
455
- context "when requested access token expired" do
456
- let(:token_for_introspection) do
457
- FactoryBot.create(:access_token, application: client, created_at: 1.year.ago)
458
- end
459
-
460
- it "responds with only active state" do
461
- request.headers["Authorization"] = basic_auth_header_for_client(client)
462
-
463
- post :introspect, params: { token: token_for_introspection.token }
464
-
465
- should_have_json "active", false
466
- expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
467
- end
468
- end
469
-
470
- context "when requested Access Token revoked" do
471
- let(:token_for_introspection) do
472
- FactoryBot.create(:access_token, application: client, revoked_at: 1.year.ago)
473
- end
474
-
475
- it "responds with only active state" do
476
- request.headers["Authorization"] = basic_auth_header_for_client(client)
477
-
478
- post :introspect, params: { token: token_for_introspection.token }
479
-
480
- should_have_json "active", false
481
- expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
482
- end
483
- end
484
-
485
- context "unauthorized (no bearer token or client credentials)" do
486
- let(:token_for_introspection) { FactoryBot.create(:access_token) }
487
-
488
- it "responds with invalid_request error" do
489
- post :introspect, params: { token: token_for_introspection.token }
490
-
491
- expect(response).not_to be_successful
492
- response_status_should_be 400
493
-
494
- should_not_have_json "active"
495
- should_have_json "error", "invalid_request"
496
- end
497
- end
498
- end
499
- end