doorkeeper 5.3.2 → 5.5.0.rc1

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 (231) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +106 -2
  3. data/README.md +6 -4
  4. data/app/controllers/doorkeeper/applications_controller.rb +4 -4
  5. data/app/controllers/doorkeeper/authorizations_controller.rb +32 -12
  6. data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -2
  7. data/app/controllers/doorkeeper/tokens_controller.rb +60 -20
  8. data/app/views/doorkeeper/applications/_form.html.erb +1 -1
  9. data/app/views/doorkeeper/applications/show.html.erb +19 -2
  10. data/config/locales/en.yml +3 -2
  11. data/lib/doorkeeper.rb +107 -79
  12. data/lib/doorkeeper/config.rb +140 -94
  13. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  14. data/lib/doorkeeper/config/option.rb +26 -14
  15. data/lib/doorkeeper/config/validations.rb +53 -0
  16. data/lib/doorkeeper/engine.rb +1 -1
  17. data/lib/doorkeeper/grant_flow.rb +43 -0
  18. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  19. data/lib/doorkeeper/grant_flow/flow.rb +34 -0
  20. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  21. data/lib/doorkeeper/grape/helpers.rb +1 -1
  22. data/lib/doorkeeper/helpers/controller.rb +6 -4
  23. data/lib/doorkeeper/models/access_grant_mixin.rb +20 -16
  24. data/lib/doorkeeper/models/access_token_mixin.rb +110 -47
  25. data/lib/doorkeeper/models/application_mixin.rb +5 -4
  26. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  27. data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
  28. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  29. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  30. data/lib/doorkeeper/oauth/authorization/code.rb +15 -6
  31. data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
  32. data/lib/doorkeeper/oauth/authorization/token.rb +14 -16
  33. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  34. data/lib/doorkeeper/oauth/authorization_code_request.rb +17 -14
  35. data/lib/doorkeeper/oauth/base_request.rb +12 -20
  36. data/lib/doorkeeper/oauth/client.rb +1 -1
  37. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  38. data/lib/doorkeeper/oauth/client_credentials/creator.rb +27 -8
  39. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +4 -2
  40. data/lib/doorkeeper/oauth/client_credentials/validator.rb +4 -2
  41. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  42. data/lib/doorkeeper/oauth/code_request.rb +3 -3
  43. data/lib/doorkeeper/oauth/code_response.rb +28 -14
  44. data/lib/doorkeeper/oauth/error_response.rb +6 -7
  45. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -8
  46. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  47. data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -2
  48. data/lib/doorkeeper/oauth/password_access_token_request.rb +24 -7
  49. data/lib/doorkeeper/oauth/pre_authorization.rb +41 -31
  50. data/lib/doorkeeper/oauth/refresh_token_request.rb +31 -22
  51. data/lib/doorkeeper/oauth/token.rb +5 -6
  52. data/lib/doorkeeper/oauth/token_introspection.rb +4 -8
  53. data/lib/doorkeeper/oauth/token_request.rb +3 -3
  54. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  55. data/lib/doorkeeper/orm/active_record.rb +10 -2
  56. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +8 -3
  57. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +7 -3
  58. data/lib/doorkeeper/orm/active_record/mixins/application.rb +20 -16
  59. data/lib/doorkeeper/rails/routes.rb +14 -18
  60. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  61. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  62. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  63. data/lib/doorkeeper/request.rb +49 -12
  64. data/lib/doorkeeper/request/refresh_token.rb +2 -1
  65. data/lib/doorkeeper/request/strategy.rb +2 -2
  66. data/lib/doorkeeper/server.rb +4 -4
  67. data/lib/doorkeeper/stale_records_cleaner.rb +4 -4
  68. data/lib/doorkeeper/version.rb +3 -3
  69. data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
  70. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  71. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +2 -0
  72. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  73. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  74. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  75. data/lib/generators/doorkeeper/templates/initializer.rb +48 -10
  76. data/lib/generators/doorkeeper/templates/migration.rb.erb +14 -5
  77. metadata +21 -299
  78. data/Appraisals +0 -40
  79. data/CODE_OF_CONDUCT.md +0 -46
  80. data/CONTRIBUTING.md +0 -49
  81. data/Dangerfile +0 -67
  82. data/Dockerfile +0 -29
  83. data/Gemfile +0 -25
  84. data/NEWS.md +0 -1
  85. data/RELEASING.md +0 -11
  86. data/Rakefile +0 -28
  87. data/SECURITY.md +0 -15
  88. data/UPGRADE.md +0 -2
  89. data/bin/console +0 -16
  90. data/doorkeeper.gemspec +0 -42
  91. data/gemfiles/rails_5_0.gemfile +0 -18
  92. data/gemfiles/rails_5_1.gemfile +0 -18
  93. data/gemfiles/rails_5_2.gemfile +0 -18
  94. data/gemfiles/rails_6_0.gemfile +0 -18
  95. data/gemfiles/rails_master.gemfile +0 -18
  96. data/spec/controllers/application_metal_controller_spec.rb +0 -64
  97. data/spec/controllers/applications_controller_spec.rb +0 -274
  98. data/spec/controllers/authorizations_controller_spec.rb +0 -608
  99. data/spec/controllers/protected_resources_controller_spec.rb +0 -361
  100. data/spec/controllers/token_info_controller_spec.rb +0 -50
  101. data/spec/controllers/tokens_controller_spec.rb +0 -498
  102. data/spec/dummy/Rakefile +0 -9
  103. data/spec/dummy/app/assets/config/manifest.js +0 -2
  104. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  105. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
  106. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
  107. data/spec/dummy/app/controllers/home_controller.rb +0 -18
  108. data/spec/dummy/app/controllers/metal_controller.rb +0 -13
  109. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
  110. data/spec/dummy/app/helpers/application_helper.rb +0 -7
  111. data/spec/dummy/app/models/user.rb +0 -7
  112. data/spec/dummy/app/views/home/index.html.erb +0 -0
  113. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  114. data/spec/dummy/config.ru +0 -6
  115. data/spec/dummy/config/application.rb +0 -49
  116. data/spec/dummy/config/boot.rb +0 -7
  117. data/spec/dummy/config/database.yml +0 -15
  118. data/spec/dummy/config/environment.rb +0 -5
  119. data/spec/dummy/config/environments/development.rb +0 -31
  120. data/spec/dummy/config/environments/production.rb +0 -64
  121. data/spec/dummy/config/environments/test.rb +0 -45
  122. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
  123. data/spec/dummy/config/initializers/doorkeeper.rb +0 -166
  124. data/spec/dummy/config/initializers/secret_token.rb +0 -10
  125. data/spec/dummy/config/initializers/session_store.rb +0 -10
  126. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  127. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  128. data/spec/dummy/config/routes.rb +0 -13
  129. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  130. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  131. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
  132. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  133. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  134. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
  135. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
  136. data/spec/dummy/db/schema.rb +0 -68
  137. data/spec/dummy/public/404.html +0 -26
  138. data/spec/dummy/public/422.html +0 -26
  139. data/spec/dummy/public/500.html +0 -26
  140. data/spec/dummy/public/favicon.ico +0 -0
  141. data/spec/dummy/script/rails +0 -9
  142. data/spec/factories.rb +0 -30
  143. data/spec/generators/application_owner_generator_spec.rb +0 -28
  144. data/spec/generators/confidential_applications_generator_spec.rb +0 -29
  145. data/spec/generators/install_generator_spec.rb +0 -36
  146. data/spec/generators/migration_generator_spec.rb +0 -28
  147. data/spec/generators/pkce_generator_spec.rb +0 -28
  148. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
  149. data/spec/generators/templates/routes.rb +0 -4
  150. data/spec/generators/views_generator_spec.rb +0 -29
  151. data/spec/grape/grape_integration_spec.rb +0 -137
  152. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
  153. data/spec/lib/config_spec.rb +0 -809
  154. data/spec/lib/doorkeeper_spec.rb +0 -27
  155. data/spec/lib/models/expirable_spec.rb +0 -61
  156. data/spec/lib/models/reusable_spec.rb +0 -40
  157. data/spec/lib/models/revocable_spec.rb +0 -59
  158. data/spec/lib/models/scopes_spec.rb +0 -53
  159. data/spec/lib/models/secret_storable_spec.rb +0 -135
  160. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
  161. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -170
  162. data/spec/lib/oauth/base_request_spec.rb +0 -224
  163. data/spec/lib/oauth/base_response_spec.rb +0 -45
  164. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  165. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -134
  166. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
  167. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
  168. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
  169. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -107
  170. data/spec/lib/oauth/client_spec.rb +0 -38
  171. data/spec/lib/oauth/code_request_spec.rb +0 -46
  172. data/spec/lib/oauth/code_response_spec.rb +0 -32
  173. data/spec/lib/oauth/error_response_spec.rb +0 -64
  174. data/spec/lib/oauth/error_spec.rb +0 -21
  175. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -20
  176. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -110
  177. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
  178. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -262
  179. data/spec/lib/oauth/invalid_request_response_spec.rb +0 -73
  180. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -53
  181. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -190
  182. data/spec/lib/oauth/pre_authorization_spec.rb +0 -223
  183. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -177
  184. data/spec/lib/oauth/scopes_spec.rb +0 -146
  185. data/spec/lib/oauth/token_request_spec.rb +0 -157
  186. data/spec/lib/oauth/token_response_spec.rb +0 -84
  187. data/spec/lib/oauth/token_spec.rb +0 -156
  188. data/spec/lib/request/strategy_spec.rb +0 -54
  189. data/spec/lib/secret_storing/base_spec.rb +0 -60
  190. data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
  191. data/spec/lib/secret_storing/plain_spec.rb +0 -44
  192. data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
  193. data/spec/lib/server_spec.rb +0 -49
  194. data/spec/lib/stale_records_cleaner_spec.rb +0 -89
  195. data/spec/models/doorkeeper/access_grant_spec.rb +0 -161
  196. data/spec/models/doorkeeper/access_token_spec.rb +0 -622
  197. data/spec/models/doorkeeper/application_spec.rb +0 -482
  198. data/spec/requests/applications/applications_request_spec.rb +0 -259
  199. data/spec/requests/applications/authorized_applications_spec.rb +0 -32
  200. data/spec/requests/endpoints/authorization_spec.rb +0 -91
  201. data/spec/requests/endpoints/token_spec.rb +0 -75
  202. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -79
  203. data/spec/requests/flows/authorization_code_spec.rb +0 -525
  204. data/spec/requests/flows/client_credentials_spec.rb +0 -166
  205. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -46
  206. data/spec/requests/flows/implicit_grant_spec.rb +0 -91
  207. data/spec/requests/flows/password_spec.rb +0 -316
  208. data/spec/requests/flows/refresh_token_spec.rb +0 -233
  209. data/spec/requests/flows/revoke_token_spec.rb +0 -157
  210. data/spec/requests/flows/skip_authorization_spec.rb +0 -66
  211. data/spec/requests/protected_resources/metal_spec.rb +0 -16
  212. data/spec/requests/protected_resources/private_api_spec.rb +0 -83
  213. data/spec/routing/custom_controller_routes_spec.rb +0 -133
  214. data/spec/routing/default_routes_spec.rb +0 -41
  215. data/spec/routing/scoped_routes_spec.rb +0 -47
  216. data/spec/spec_helper.rb +0 -54
  217. data/spec/spec_helper_integration.rb +0 -4
  218. data/spec/support/dependencies/factory_bot.rb +0 -4
  219. data/spec/support/doorkeeper_rspec.rb +0 -22
  220. data/spec/support/helpers/access_token_request_helper.rb +0 -13
  221. data/spec/support/helpers/authorization_request_helper.rb +0 -43
  222. data/spec/support/helpers/config_helper.rb +0 -11
  223. data/spec/support/helpers/model_helper.rb +0 -78
  224. data/spec/support/helpers/request_spec_helper.rb +0 -110
  225. data/spec/support/helpers/url_helper.rb +0 -62
  226. data/spec/support/orm/active_record.rb +0 -5
  227. data/spec/support/shared/controllers_shared_context.rb +0 -133
  228. data/spec/support/shared/hashing_shared_context.rb +0 -36
  229. data/spec/support/shared/models_shared_examples.rb +0 -54
  230. data/spec/validators/redirect_uri_validator_spec.rb +0 -183
  231. 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,498 +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))
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
135
- end
136
- end
137
-
138
- describe "POST #create with custom error" do
139
- it "returns the error response with a custom message" do
140
- # I18n looks for `doorkeeper.errors.messages.custom_message` in locale files
141
- custom_message = "my_message"
142
- allow(I18n).to receive(:translate)
143
- .with(
144
- custom_message,
145
- hash_including(scope: %i[doorkeeper errors messages]),
146
- )
147
- .and_return("Authorization custom message")
148
-
149
- doorkeeper_error = Doorkeeper::Errors::DoorkeeperError.new(custom_message)
150
-
151
- strategy = double(:strategy)
152
- request = double(token_request: strategy)
153
- allow(strategy).to receive(:authorize).and_raise(doorkeeper_error)
154
- allow(controller).to receive(:server).and_return(request)
155
-
156
- post :create
157
-
158
- expected_response_body = {
159
- "error" => custom_message,
160
- "error_description" => "Authorization custom message",
161
- }
162
- expect(response.status).to eq 400
163
- expect(response.headers["WWW-Authenticate"]).to match(/Bearer/)
164
- expect(JSON.parse(response.body)).to eq expected_response_body
165
- end
166
- end
167
-
168
- # http://tools.ietf.org/html/rfc7009#section-2.2
169
- describe "POST #revoke" do
170
- let(:client) { FactoryBot.create(:application) }
171
- let(:access_token) { FactoryBot.create(:access_token, application: client) }
172
-
173
- context "when associated app is public" do
174
- let(:client) { FactoryBot.create(:application, confidential: false) }
175
-
176
- it "returns 200" do
177
- post :revoke, params: { token: access_token.token }
178
-
179
- expect(response.status).to eq 200
180
- end
181
-
182
- it "revokes the access token" do
183
- post :revoke, params: { token: access_token.token }
184
-
185
- expect(access_token.reload).to have_attributes(revoked?: true)
186
- end
187
- end
188
-
189
- context "when associated app is confidential" do
190
- let(:client) { FactoryBot.create(:application, confidential: true) }
191
- let(:oauth_client) { Doorkeeper::OAuth::Client.new(client) }
192
-
193
- before(:each) do
194
- allow_any_instance_of(Doorkeeper::Server).to receive(:client) { oauth_client }
195
- end
196
-
197
- it "returns 200" do
198
- post :revoke, params: { token: access_token.token }
199
-
200
- expect(response.status).to eq 200
201
- end
202
-
203
- it "revokes the access token" do
204
- post :revoke, params: { token: access_token.token }
205
-
206
- expect(access_token.reload).to have_attributes(revoked?: true)
207
- end
208
-
209
- context "when authorization fails" do
210
- let(:some_other_client) { FactoryBot.create(:application, confidential: true) }
211
- let(:oauth_client) { Doorkeeper::OAuth::Client.new(some_other_client) }
212
-
213
- it "returns 403" do
214
- post :revoke, params: { token: access_token.token }
215
-
216
- expect(response.status).to eq 403
217
- end
218
-
219
- it "does not revoke the access token" do
220
- post :revoke, params: { token: access_token.token }
221
-
222
- expect(access_token.reload).to have_attributes(revoked?: false)
223
- end
224
- end
225
- end
226
- end
227
-
228
- describe "POST #introspect" do
229
- let(:client) { FactoryBot.create(:application) }
230
- let(:access_token) { FactoryBot.create(:access_token, application: client) }
231
- let(:token_for_introspection) { FactoryBot.create(:access_token, application: client) }
232
-
233
- context "authorized using valid Bearer token" do
234
- it "responds with full token introspection" do
235
- request.headers["Authorization"] = "Bearer #{access_token.token}"
236
-
237
- post :introspect, params: { token: token_for_introspection.token }
238
-
239
- should_have_json "active", true
240
- expect(json_response).to include("client_id", "token_type", "exp", "iat")
241
- end
242
- end
243
-
244
- context "authorized using Client Credentials of the client that token is issued to" do
245
- it "responds with full token introspection" do
246
- request.headers["Authorization"] = basic_auth_header_for_client(client)
247
-
248
- post :introspect, params: { token: token_for_introspection.token }
249
-
250
- should_have_json "active", true
251
- expect(json_response).to include("client_id", "token_type", "exp", "iat")
252
- should_have_json "client_id", client.uid
253
- end
254
- end
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
-
276
- context "using custom introspection response" do
277
- before do
278
- Doorkeeper.configure do
279
- orm DOORKEEPER_ORM
280
- custom_introspection_response do |_token, _context|
281
- {
282
- sub: "Z5O3upPC88QrAjx00dis",
283
- aud: "https://protected.example.net/resource",
284
- }
285
- end
286
- end
287
- end
288
-
289
- it "responds with full token introspection" do
290
- request.headers["Authorization"] = "Bearer #{access_token.token}"
291
-
292
- post :introspect, params: { token: token_for_introspection.token }
293
-
294
- expect(json_response).to include("client_id", "token_type", "exp", "iat", "sub", "aud")
295
- should_have_json "sub", "Z5O3upPC88QrAjx00dis"
296
- should_have_json "aud", "https://protected.example.net/resource"
297
- end
298
- end
299
-
300
- context "public access token" do
301
- let(:token_for_introspection) { FactoryBot.create(:access_token, application: nil) }
302
-
303
- it "responds with full token introspection" do
304
- request.headers["Authorization"] = basic_auth_header_for_client(client)
305
-
306
- post :introspect, params: { token: token_for_introspection.token }
307
-
308
- should_have_json "active", true
309
- expect(json_response).to include("client_id", "token_type", "exp", "iat")
310
- should_have_json "client_id", nil
311
- end
312
- end
313
-
314
- context "token was issued to a different client than is making this request" do
315
- let(:different_client) { FactoryBot.create(:application) }
316
-
317
- it "responds with only active state" do
318
- request.headers["Authorization"] = basic_auth_header_for_client(different_client)
319
-
320
- post :introspect, params: { token: token_for_introspection.token }
321
-
322
- expect(response).to be_successful
323
-
324
- should_have_json "active", false
325
- expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
326
- end
327
- end
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
-
381
- context "authorized using invalid Bearer token" do
382
- let(:access_token) do
383
- FactoryBot.create(:access_token, application: client, revoked_at: 1.day.ago)
384
- end
385
-
386
- it "responds with invalid_token error" do
387
- request.headers["Authorization"] = "Bearer #{access_token.token}"
388
-
389
- post :introspect, params: { token: token_for_introspection.token }
390
-
391
- response_status_should_be 401
392
-
393
- should_not_have_json "active"
394
- should_have_json "error", "invalid_token"
395
- end
396
- end
397
-
398
- context "authorized using the Bearer token that need to be introspected" do
399
- it "responds with invalid token error" do
400
- request.headers["Authorization"] = "Bearer #{access_token.token}"
401
-
402
- post :introspect, params: { token: access_token.token }
403
-
404
- response_status_should_be 401
405
-
406
- should_not_have_json "active"
407
- should_have_json "error", "invalid_token"
408
- end
409
- end
410
-
411
- context "using invalid credentials to authorize" do
412
- let(:client) { double(uid: "123123", secret: "666999") }
413
- let(:access_token) { FactoryBot.create(:access_token) }
414
-
415
- it "responds with invalid_client error" do
416
- request.headers["Authorization"] = basic_auth_header_for_client(client)
417
-
418
- post :introspect, params: { token: access_token.token }
419
-
420
- expect(response).not_to be_successful
421
- response_status_should_be 401
422
-
423
- should_not_have_json "active"
424
- should_have_json "error", "invalid_client"
425
- end
426
- end
427
-
428
- context "using wrong token value" do
429
- context "authorized using client credentials" do
430
- it "responds with only active state" do
431
- request.headers["Authorization"] = basic_auth_header_for_client(client)
432
-
433
- post :introspect, params: { token: SecureRandom.hex(16) }
434
-
435
- should_have_json "active", false
436
- expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
437
- end
438
- end
439
-
440
- context "authorized using valid Bearer token" do
441
- it "responds with invalid_token error" do
442
- request.headers["Authorization"] = "Bearer #{access_token.token}"
443
-
444
- post :introspect, params: { token: SecureRandom.hex(16) }
445
-
446
- response_status_should_be 401
447
-
448
- should_not_have_json "active"
449
- should_have_json "error", "invalid_token"
450
- end
451
- end
452
- end
453
-
454
- context "when requested access token expired" do
455
- let(:token_for_introspection) do
456
- FactoryBot.create(:access_token, application: client, created_at: 1.year.ago)
457
- end
458
-
459
- it "responds with only active state" do
460
- request.headers["Authorization"] = basic_auth_header_for_client(client)
461
-
462
- post :introspect, params: { token: token_for_introspection.token }
463
-
464
- should_have_json "active", false
465
- expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
466
- end
467
- end
468
-
469
- context "when requested Access Token revoked" do
470
- let(:token_for_introspection) do
471
- FactoryBot.create(:access_token, application: client, revoked_at: 1.year.ago)
472
- end
473
-
474
- it "responds with only active state" do
475
- request.headers["Authorization"] = basic_auth_header_for_client(client)
476
-
477
- post :introspect, params: { token: token_for_introspection.token }
478
-
479
- should_have_json "active", false
480
- expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
481
- end
482
- end
483
-
484
- context "unauthorized (no bearer token or client credentials)" do
485
- let(:token_for_introspection) { FactoryBot.create(:access_token) }
486
-
487
- it "responds with invalid_request error" do
488
- post :introspect, params: { token: token_for_introspection.token }
489
-
490
- expect(response).not_to be_successful
491
- response_status_should_be 400
492
-
493
- should_not_have_json "active"
494
- should_have_json "error", "invalid_request"
495
- end
496
- end
497
- end
498
- end