doorkeeper 5.3.3 → 5.4.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 (224) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +82 -4
  3. data/README.md +6 -4
  4. data/app/controllers/doorkeeper/applications_controller.rb +4 -4
  5. data/app/controllers/doorkeeper/authorizations_controller.rb +31 -12
  6. data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -2
  7. data/app/controllers/doorkeeper/tokens_controller.rb +57 -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 -1
  11. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  12. data/lib/doorkeeper/config/option.rb +28 -14
  13. data/lib/doorkeeper/config.rb +64 -35
  14. data/lib/doorkeeper/engine.rb +1 -1
  15. data/lib/doorkeeper/grape/helpers.rb +1 -1
  16. data/lib/doorkeeper/helpers/controller.rb +4 -4
  17. data/lib/doorkeeper/models/access_grant_mixin.rb +20 -16
  18. data/lib/doorkeeper/models/access_token_mixin.rb +108 -45
  19. data/lib/doorkeeper/models/application_mixin.rb +5 -4
  20. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  21. data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
  22. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  23. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  24. data/lib/doorkeeper/oauth/authorization/code.rb +15 -6
  25. data/lib/doorkeeper/oauth/authorization/context.rb +2 -2
  26. data/lib/doorkeeper/oauth/authorization/token.rb +8 -12
  27. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  28. data/lib/doorkeeper/oauth/authorization_code_request.rb +18 -8
  29. data/lib/doorkeeper/oauth/base_request.rb +11 -19
  30. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  31. data/lib/doorkeeper/oauth/client.rb +1 -1
  32. data/lib/doorkeeper/oauth/client_credentials/creator.rb +26 -8
  33. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
  34. data/lib/doorkeeper/oauth/client_credentials/validator.rb +4 -2
  35. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  36. data/lib/doorkeeper/oauth/code_request.rb +3 -3
  37. data/lib/doorkeeper/oauth/code_response.rb +6 -2
  38. data/lib/doorkeeper/oauth/error_response.rb +2 -4
  39. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -5
  40. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  41. data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -2
  42. data/lib/doorkeeper/oauth/password_access_token_request.rb +4 -6
  43. data/lib/doorkeeper/oauth/pre_authorization.rb +36 -30
  44. data/lib/doorkeeper/oauth/refresh_token_request.rb +18 -22
  45. data/lib/doorkeeper/oauth/token.rb +5 -6
  46. data/lib/doorkeeper/oauth/token_introspection.rb +4 -8
  47. data/lib/doorkeeper/oauth/token_request.rb +3 -3
  48. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  49. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +8 -3
  50. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +7 -3
  51. data/lib/doorkeeper/orm/active_record.rb +10 -2
  52. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  53. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  54. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  55. data/lib/doorkeeper/rails/routes.rb +13 -17
  56. data/lib/doorkeeper/request/refresh_token.rb +2 -1
  57. data/lib/doorkeeper/request/strategy.rb +2 -2
  58. data/lib/doorkeeper/server.rb +4 -4
  59. data/lib/doorkeeper/stale_records_cleaner.rb +4 -4
  60. data/lib/doorkeeper/version.rb +2 -2
  61. data/lib/doorkeeper.rb +106 -79
  62. data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
  63. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  64. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +2 -0
  65. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  66. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  67. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  68. data/lib/generators/doorkeeper/templates/initializer.rb +39 -3
  69. data/lib/generators/doorkeeper/templates/migration.rb.erb +14 -5
  70. metadata +13 -296
  71. data/Appraisals +0 -40
  72. data/CODE_OF_CONDUCT.md +0 -46
  73. data/CONTRIBUTING.md +0 -49
  74. data/Dangerfile +0 -67
  75. data/Dockerfile +0 -29
  76. data/Gemfile +0 -25
  77. data/NEWS.md +0 -1
  78. data/RELEASING.md +0 -11
  79. data/Rakefile +0 -28
  80. data/SECURITY.md +0 -15
  81. data/UPGRADE.md +0 -2
  82. data/bin/console +0 -16
  83. data/doorkeeper.gemspec +0 -42
  84. data/gemfiles/rails_5_0.gemfile +0 -18
  85. data/gemfiles/rails_5_1.gemfile +0 -18
  86. data/gemfiles/rails_5_2.gemfile +0 -18
  87. data/gemfiles/rails_6_0.gemfile +0 -18
  88. data/gemfiles/rails_master.gemfile +0 -18
  89. data/spec/controllers/application_metal_controller_spec.rb +0 -64
  90. data/spec/controllers/applications_controller_spec.rb +0 -274
  91. data/spec/controllers/authorizations_controller_spec.rb +0 -608
  92. data/spec/controllers/protected_resources_controller_spec.rb +0 -361
  93. data/spec/controllers/token_info_controller_spec.rb +0 -50
  94. data/spec/controllers/tokens_controller_spec.rb +0 -498
  95. data/spec/dummy/Rakefile +0 -9
  96. data/spec/dummy/app/assets/config/manifest.js +0 -2
  97. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  98. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
  99. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
  100. data/spec/dummy/app/controllers/home_controller.rb +0 -18
  101. data/spec/dummy/app/controllers/metal_controller.rb +0 -13
  102. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
  103. data/spec/dummy/app/helpers/application_helper.rb +0 -7
  104. data/spec/dummy/app/models/user.rb +0 -7
  105. data/spec/dummy/app/views/home/index.html.erb +0 -0
  106. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  107. data/spec/dummy/config/application.rb +0 -49
  108. data/spec/dummy/config/boot.rb +0 -7
  109. data/spec/dummy/config/database.yml +0 -15
  110. data/spec/dummy/config/environment.rb +0 -5
  111. data/spec/dummy/config/environments/development.rb +0 -31
  112. data/spec/dummy/config/environments/production.rb +0 -64
  113. data/spec/dummy/config/environments/test.rb +0 -45
  114. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
  115. data/spec/dummy/config/initializers/doorkeeper.rb +0 -166
  116. data/spec/dummy/config/initializers/secret_token.rb +0 -10
  117. data/spec/dummy/config/initializers/session_store.rb +0 -10
  118. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  119. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  120. data/spec/dummy/config/routes.rb +0 -13
  121. data/spec/dummy/config.ru +0 -6
  122. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  123. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  124. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
  125. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  126. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  127. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
  128. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
  129. data/spec/dummy/db/schema.rb +0 -68
  130. data/spec/dummy/public/404.html +0 -26
  131. data/spec/dummy/public/422.html +0 -26
  132. data/spec/dummy/public/500.html +0 -26
  133. data/spec/dummy/public/favicon.ico +0 -0
  134. data/spec/dummy/script/rails +0 -9
  135. data/spec/factories.rb +0 -30
  136. data/spec/generators/application_owner_generator_spec.rb +0 -28
  137. data/spec/generators/confidential_applications_generator_spec.rb +0 -29
  138. data/spec/generators/install_generator_spec.rb +0 -36
  139. data/spec/generators/migration_generator_spec.rb +0 -28
  140. data/spec/generators/pkce_generator_spec.rb +0 -28
  141. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
  142. data/spec/generators/templates/routes.rb +0 -4
  143. data/spec/generators/views_generator_spec.rb +0 -29
  144. data/spec/grape/grape_integration_spec.rb +0 -137
  145. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
  146. data/spec/lib/config_spec.rb +0 -809
  147. data/spec/lib/doorkeeper_spec.rb +0 -27
  148. data/spec/lib/models/expirable_spec.rb +0 -61
  149. data/spec/lib/models/reusable_spec.rb +0 -40
  150. data/spec/lib/models/revocable_spec.rb +0 -59
  151. data/spec/lib/models/scopes_spec.rb +0 -53
  152. data/spec/lib/models/secret_storable_spec.rb +0 -135
  153. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
  154. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -170
  155. data/spec/lib/oauth/base_request_spec.rb +0 -224
  156. data/spec/lib/oauth/base_response_spec.rb +0 -45
  157. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  158. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -134
  159. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
  160. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
  161. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
  162. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -107
  163. data/spec/lib/oauth/client_spec.rb +0 -38
  164. data/spec/lib/oauth/code_request_spec.rb +0 -46
  165. data/spec/lib/oauth/code_response_spec.rb +0 -32
  166. data/spec/lib/oauth/error_response_spec.rb +0 -64
  167. data/spec/lib/oauth/error_spec.rb +0 -21
  168. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -20
  169. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -110
  170. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
  171. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -262
  172. data/spec/lib/oauth/invalid_request_response_spec.rb +0 -73
  173. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -53
  174. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -190
  175. data/spec/lib/oauth/pre_authorization_spec.rb +0 -223
  176. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -177
  177. data/spec/lib/oauth/scopes_spec.rb +0 -146
  178. data/spec/lib/oauth/token_request_spec.rb +0 -157
  179. data/spec/lib/oauth/token_response_spec.rb +0 -84
  180. data/spec/lib/oauth/token_spec.rb +0 -156
  181. data/spec/lib/request/strategy_spec.rb +0 -54
  182. data/spec/lib/secret_storing/base_spec.rb +0 -60
  183. data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
  184. data/spec/lib/secret_storing/plain_spec.rb +0 -44
  185. data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
  186. data/spec/lib/server_spec.rb +0 -49
  187. data/spec/lib/stale_records_cleaner_spec.rb +0 -89
  188. data/spec/models/doorkeeper/access_grant_spec.rb +0 -161
  189. data/spec/models/doorkeeper/access_token_spec.rb +0 -622
  190. data/spec/models/doorkeeper/application_spec.rb +0 -482
  191. data/spec/requests/applications/applications_request_spec.rb +0 -259
  192. data/spec/requests/applications/authorized_applications_spec.rb +0 -32
  193. data/spec/requests/endpoints/authorization_spec.rb +0 -91
  194. data/spec/requests/endpoints/token_spec.rb +0 -75
  195. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -79
  196. data/spec/requests/flows/authorization_code_spec.rb +0 -525
  197. data/spec/requests/flows/client_credentials_spec.rb +0 -166
  198. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -46
  199. data/spec/requests/flows/implicit_grant_spec.rb +0 -91
  200. data/spec/requests/flows/password_spec.rb +0 -316
  201. data/spec/requests/flows/refresh_token_spec.rb +0 -233
  202. data/spec/requests/flows/revoke_token_spec.rb +0 -157
  203. data/spec/requests/flows/skip_authorization_spec.rb +0 -66
  204. data/spec/requests/protected_resources/metal_spec.rb +0 -16
  205. data/spec/requests/protected_resources/private_api_spec.rb +0 -83
  206. data/spec/routing/custom_controller_routes_spec.rb +0 -133
  207. data/spec/routing/default_routes_spec.rb +0 -41
  208. data/spec/routing/scoped_routes_spec.rb +0 -47
  209. data/spec/spec_helper.rb +0 -54
  210. data/spec/spec_helper_integration.rb +0 -4
  211. data/spec/support/dependencies/factory_bot.rb +0 -4
  212. data/spec/support/doorkeeper_rspec.rb +0 -22
  213. data/spec/support/helpers/access_token_request_helper.rb +0 -13
  214. data/spec/support/helpers/authorization_request_helper.rb +0 -43
  215. data/spec/support/helpers/config_helper.rb +0 -11
  216. data/spec/support/helpers/model_helper.rb +0 -78
  217. data/spec/support/helpers/request_spec_helper.rb +0 -110
  218. data/spec/support/helpers/url_helper.rb +0 -62
  219. data/spec/support/orm/active_record.rb +0 -5
  220. data/spec/support/shared/controllers_shared_context.rb +0 -133
  221. data/spec/support/shared/hashing_shared_context.rb +0 -36
  222. data/spec/support/shared/models_shared_examples.rb +0 -54
  223. data/spec/validators/redirect_uri_validator_spec.rb +0 -183
  224. data/spec/version/version_spec.rb +0 -17
@@ -1,525 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- feature "Authorization Code Flow" do
6
- background do
7
- default_scopes_exist :default
8
- config_is_set(:authenticate_resource_owner) { User.first || redirect_to("/sign_in") }
9
- client_exists
10
- create_resource_owner
11
- sign_in
12
- end
13
-
14
- scenario "resource owner authorizes the client" do
15
- visit authorization_endpoint_url(client: @client)
16
- click_on "Authorize"
17
-
18
- access_grant_should_exist_for(@client, @resource_owner)
19
-
20
- i_should_be_on_client_callback(@client)
21
-
22
- url_should_have_param("code", Doorkeeper::AccessGrant.first.token)
23
- url_should_not_have_param("state")
24
- url_should_not_have_param("error")
25
- end
26
-
27
- context "when configured to check application supported grant flow" do
28
- before do
29
- config_is_set(:allow_grant_flow_for_client, ->(_grant_flow, client) { client.name == "admin" })
30
- end
31
-
32
- scenario "forbids the request when doesn't satisfy condition" do
33
- @client.update(name: "sample app")
34
-
35
- visit authorization_endpoint_url(client: @client)
36
-
37
- i_should_see_translated_error_message("unauthorized_client")
38
- end
39
-
40
- scenario "allows the request when satisfies condition" do
41
- @client.update(name: "admin")
42
-
43
- visit authorization_endpoint_url(client: @client)
44
- i_should_not_see_translated_error_message("unauthorized_client")
45
- click_on "Authorize"
46
-
47
- authorization_code = Doorkeeper::AccessGrant.first.token
48
- create_access_token authorization_code, @client
49
-
50
- access_token_should_exist_for(@client, @resource_owner)
51
-
52
- should_not_have_json "error"
53
-
54
- should_have_json "access_token", Doorkeeper::AccessToken.first.token
55
- should_have_json "token_type", "Bearer"
56
- should_have_json_within "expires_in", Doorkeeper::AccessToken.first.expires_in, 1
57
- end
58
- end
59
-
60
- context "with grant hashing enabled" do
61
- background do
62
- config_is_set(:token_secret_strategy, ::Doorkeeper::SecretStoring::Sha256Hash)
63
- end
64
-
65
- def authorize(redirect_url)
66
- @client.redirect_uri = redirect_url
67
- @client.save!
68
- visit authorization_endpoint_url(client: @client)
69
- click_on "Authorize"
70
-
71
- access_grant_should_exist_for(@client, @resource_owner)
72
-
73
- code = current_params["code"]
74
- expect(code).not_to be_nil
75
-
76
- hashed_code = Doorkeeper::AccessGrant.secret_strategy.transform_secret code
77
- expect(hashed_code).to eq Doorkeeper::AccessGrant.first.token
78
-
79
- [code, hashed_code]
80
- end
81
-
82
- scenario "using redirect_url urn:ietf:wg:oauth:2.0:oob" do
83
- code, hashed_code = authorize("urn:ietf:wg:oauth:2.0:oob")
84
- expect(code).not_to eq(hashed_code)
85
- i_should_see "Authorization code:"
86
- i_should_see code
87
- i_should_not_see hashed_code
88
- end
89
-
90
- scenario "using redirect_url urn:ietf:wg:oauth:2.0:oob:auto" do
91
- code, hashed_code = authorize("urn:ietf:wg:oauth:2.0:oob:auto")
92
- expect(code).not_to eq(hashed_code)
93
- i_should_see "Authorization code:"
94
- i_should_see code
95
- i_should_not_see hashed_code
96
- end
97
- end
98
-
99
- scenario "resource owner authorizes using oob url" do
100
- @client.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
101
- @client.save!
102
- visit authorization_endpoint_url(client: @client)
103
- click_on "Authorize"
104
-
105
- access_grant_should_exist_for(@client, @resource_owner)
106
-
107
- url_should_have_param("code", Doorkeeper::AccessGrant.first.token)
108
- i_should_see "Authorization code:"
109
- i_should_see Doorkeeper::AccessGrant.first.token
110
- end
111
-
112
- scenario "resource owner authorizes the client with state parameter set" do
113
- visit authorization_endpoint_url(client: @client, state: "return-me")
114
- click_on "Authorize"
115
- url_should_have_param("code", Doorkeeper::AccessGrant.first.token)
116
- url_should_have_param("state", "return-me")
117
- url_should_not_have_param("code_challenge_method")
118
- end
119
-
120
- scenario "resource owner requests an access token without authorization code" do
121
- create_access_token "", @client
122
-
123
- access_token_should_not_exist
124
-
125
- expect(Doorkeeper::AccessToken.count).to be_zero
126
-
127
- should_have_json "error", "invalid_request"
128
- should_have_json "error_description", translated_invalid_request_error_message(:missing_param, :code)
129
- end
130
-
131
- scenario "resource owner requests an access token with authorization code" do
132
- visit authorization_endpoint_url(client: @client)
133
- click_on "Authorize"
134
-
135
- authorization_code = Doorkeeper::AccessGrant.first.token
136
- create_access_token authorization_code, @client
137
-
138
- access_token_should_exist_for(@client, @resource_owner)
139
-
140
- should_not_have_json "error"
141
-
142
- should_have_json "access_token", Doorkeeper::AccessToken.first.token
143
- should_have_json "token_type", "Bearer"
144
- should_have_json_within "expires_in", Doorkeeper::AccessToken.first.expires_in, 1
145
- end
146
-
147
- scenario "resource owner requests an access token with authorization code but without secret" do
148
- visit authorization_endpoint_url(client: @client)
149
- click_on "Authorize"
150
-
151
- authorization_code = Doorkeeper::AccessGrant.first.token
152
- page.driver.post token_endpoint_url(
153
- code: authorization_code, client_id: @client.uid,
154
- redirect_uri: @client.redirect_uri,
155
- )
156
-
157
- expect(Doorkeeper::AccessToken.count).to be_zero
158
-
159
- should_have_json "error", "invalid_client"
160
- should_have_json "error_description", translated_error_message(:invalid_client)
161
- end
162
-
163
- scenario "resource owner requests an access token with authorization code but without client id" do
164
- visit authorization_endpoint_url(client: @client)
165
- click_on "Authorize"
166
-
167
- authorization_code = Doorkeeper::AccessGrant.first.token
168
- page.driver.post token_endpoint_url(
169
- code: authorization_code, client_secret: @client.secret,
170
- redirect_uri: @client.redirect_uri,
171
- )
172
-
173
- expect(Doorkeeper::AccessToken.count).to be_zero
174
-
175
- should_have_json "error", "invalid_client"
176
- should_have_json "error_description", translated_error_message(:invalid_client)
177
- end
178
-
179
- scenario "silently authorizes if matching token exists" do
180
- default_scopes_exist :public, :write
181
-
182
- access_token_exists application: @client,
183
- expires_in: -100, # even expired token
184
- resource_owner_id: @resource_owner.id,
185
- scopes: "public write"
186
-
187
- visit authorization_endpoint_url(client: @client, scope: "public write")
188
-
189
- response_status_should_be 200
190
- i_should_not_see "Authorize"
191
- end
192
-
193
- context "with PKCE" do
194
- context "plain" do
195
- let(:code_challenge) { "a45a9fea-0676-477e-95b1-a40f72ac3cfb" }
196
- let(:code_verifier) { "a45a9fea-0676-477e-95b1-a40f72ac3cfb" }
197
-
198
- scenario "resource owner authorizes the client with code_challenge parameter set" do
199
- visit authorization_endpoint_url(
200
- client: @client,
201
- code_challenge: code_challenge,
202
- code_challenge_method: "plain",
203
- )
204
- click_on "Authorize"
205
-
206
- url_should_have_param("code", Doorkeeper::AccessGrant.first.token)
207
- url_should_not_have_param("code_challenge_method")
208
- url_should_not_have_param("code_challenge")
209
- end
210
-
211
- scenario "mobile app requests an access token with authorization code but not pkce token" do
212
- visit authorization_endpoint_url(client: @client)
213
- click_on "Authorize"
214
-
215
- authorization_code = current_params["code"]
216
- create_access_token authorization_code, @client, code_verifier
217
-
218
- should_have_json "error", "invalid_grant"
219
- should_have_json "error_description", translated_error_message(:invalid_grant)
220
- end
221
-
222
- scenario "mobile app requests an access token with authorization code and plain code challenge method" do
223
- visit authorization_endpoint_url(
224
- client: @client,
225
- code_challenge: code_challenge,
226
- code_challenge_method: "plain",
227
- )
228
- click_on "Authorize"
229
-
230
- authorization_code = current_params["code"]
231
- create_access_token authorization_code, @client, code_verifier
232
-
233
- access_token_should_exist_for(@client, @resource_owner)
234
-
235
- should_not_have_json "error"
236
-
237
- should_have_json "access_token", Doorkeeper::AccessToken.first.token
238
- should_have_json "token_type", "Bearer"
239
- should_have_json_within "expires_in", Doorkeeper::AccessToken.first.expires_in, 1
240
- end
241
-
242
- scenario "mobile app requests an access token with authorization code but without code_verifier" do
243
- visit authorization_endpoint_url(
244
- client: @client,
245
- code_challenge: code_challenge,
246
- code_challenge_method: "plain",
247
- )
248
- click_on "Authorize"
249
-
250
- authorization_code = current_params["code"]
251
- create_access_token authorization_code, @client, nil
252
-
253
- should_not_have_json "access_token"
254
- should_have_json "error", "invalid_request"
255
- should_have_json "error_description", translated_invalid_request_error_message(:missing_param, :code_verifier)
256
- end
257
-
258
- scenario "mobile app requests an access token with authorization code with wrong code_verifier" do
259
- visit authorization_endpoint_url(
260
- client: @client,
261
- code_challenge: code_challenge,
262
- code_challenge_method: "plain",
263
- )
264
- click_on "Authorize"
265
-
266
- authorization_code = current_params["code"]
267
- create_access_token authorization_code, @client, "wrong_code_verifier"
268
-
269
- should_not_have_json "access_token"
270
- should_have_json "error", "invalid_grant"
271
- should_have_json "error_description", translated_error_message(:invalid_grant)
272
- end
273
- end
274
-
275
- context "s256" do
276
- let(:code_challenge) { "Oz733NtQ0rJP8b04fgZMJMwprn6Iw8sMCT_9bR1q4tA" }
277
- let(:code_verifier) { "a45a9fea-0676-477e-95b1-a40f72ac3cfb" }
278
-
279
- scenario "resource owner authorizes the client with code_challenge parameter set" do
280
- visit authorization_endpoint_url(
281
- client: @client,
282
- code_challenge: code_challenge,
283
- code_challenge_method: "S256",
284
- )
285
- click_on "Authorize"
286
-
287
- url_should_have_param("code", Doorkeeper::AccessGrant.first.token)
288
- url_should_not_have_param("code_challenge_method")
289
- url_should_not_have_param("code_challenge")
290
- end
291
-
292
- scenario "mobile app requests an access token with authorization code and S256 code challenge method" do
293
- visit authorization_endpoint_url(
294
- client: @client,
295
- code_challenge: code_challenge,
296
- code_challenge_method: "S256",
297
- )
298
- click_on "Authorize"
299
-
300
- authorization_code = current_params["code"]
301
- create_access_token authorization_code, @client, code_verifier
302
-
303
- access_token_should_exist_for(@client, @resource_owner)
304
-
305
- should_not_have_json "error"
306
-
307
- should_have_json "access_token", Doorkeeper::AccessToken.first.token
308
- should_have_json "token_type", "Bearer"
309
- should_have_json_within "expires_in", Doorkeeper::AccessToken.first.expires_in, 1
310
- end
311
-
312
- scenario "mobile app requests an access token with authorization code and without secret" do
313
- visit authorization_endpoint_url(
314
- client: @client,
315
- code_challenge: code_challenge,
316
- code_challenge_method: "S256",
317
- )
318
- click_on "Authorize"
319
-
320
- authorization_code = current_params["code"]
321
- page.driver.post token_endpoint_url(
322
- code: authorization_code,
323
- client_id: @client.uid,
324
- redirect_uri: @client.redirect_uri,
325
- code_verifier: code_verifier,
326
- )
327
- should_not_have_json "access_token"
328
- should_have_json "error", "invalid_client"
329
- should_have_json "error_description", translated_error_message(:invalid_client)
330
- end
331
-
332
- scenario "mobile app requests an access token with authorization code and without secret but is marked as not confidential" do
333
- @client.update_attribute :confidential, false
334
- visit authorization_endpoint_url(client: @client, code_challenge: code_challenge, code_challenge_method: "S256")
335
- click_on "Authorize"
336
-
337
- authorization_code = current_params["code"]
338
- page.driver.post token_endpoint_url(
339
- code: authorization_code,
340
- client_id: @client.uid,
341
- redirect_uri: @client.redirect_uri,
342
- code_verifier: code_verifier,
343
- )
344
- should_not_have_json "error"
345
-
346
- should_have_json "access_token", Doorkeeper::AccessToken.first.token
347
- should_have_json "token_type", "Bearer"
348
- should_have_json_within "expires_in", Doorkeeper::AccessToken.first.expires_in, 1
349
- end
350
-
351
- scenario "mobile app requests an access token with authorization code but no code verifier" do
352
- visit authorization_endpoint_url(
353
- client: @client,
354
- code_challenge: code_challenge,
355
- code_challenge_method: "S256",
356
- )
357
- click_on "Authorize"
358
-
359
- authorization_code = current_params["code"]
360
- create_access_token authorization_code, @client
361
-
362
- should_not_have_json "access_token"
363
- should_have_json "error", "invalid_request"
364
- should_have_json "error_description", translated_invalid_request_error_message(:missing_param, :code_verifier)
365
- end
366
-
367
- scenario "mobile app requests an access token with authorization code with wrong verifier" do
368
- visit authorization_endpoint_url(
369
- client: @client,
370
- code_challenge: code_challenge,
371
- code_challenge_method: "S256",
372
- )
373
- click_on "Authorize"
374
-
375
- authorization_code = current_params["code"]
376
- create_access_token authorization_code, @client, "incorrect-code-verifier"
377
-
378
- should_not_have_json "access_token"
379
- should_have_json "error", "invalid_grant"
380
- should_have_json "error_description", translated_error_message(:invalid_grant)
381
- end
382
-
383
- scenario "code_challenge_mehthod in token request is totally ignored" do
384
- visit authorization_endpoint_url(
385
- client: @client,
386
- code_challenge: code_challenge,
387
- code_challenge_method: "S256",
388
- )
389
- click_on "Authorize"
390
-
391
- authorization_code = current_params["code"]
392
- page.driver.post token_endpoint_url(
393
- code: authorization_code,
394
- client: @client,
395
- code_verifier: code_challenge,
396
- code_challenge_method: "plain",
397
- )
398
-
399
- should_not_have_json "access_token"
400
- should_have_json "error", "invalid_grant"
401
- should_have_json "error_description", translated_error_message(:invalid_grant)
402
- end
403
-
404
- scenario "expects to set code_challenge_method explicitely without fallback" do
405
- visit authorization_endpoint_url(client: @client, code_challenge: code_challenge)
406
- expect(page).to have_content("The code challenge method must be plain or S256.")
407
- end
408
- end
409
- end
410
-
411
- context "when application scopes are present and no scope is passed" do
412
- background do
413
- @client.update(scopes: "public write read default")
414
- end
415
-
416
- scenario "scope is invalid because default scope is different from application scope" do
417
- default_scopes_exist :admin
418
- visit authorization_endpoint_url(client: @client)
419
- response_status_should_be 200
420
- i_should_not_see "Authorize"
421
- i_should_see_translated_error_message :invalid_scope
422
- end
423
-
424
- scenario "access grant have scopes which are common in application scopees and default scopes" do
425
- default_scopes_exist :public, :write
426
- visit authorization_endpoint_url(client: @client)
427
- click_on "Authorize"
428
- access_grant_should_exist_for(@client, @resource_owner)
429
- access_grant_should_have_scopes :public, :write
430
- end
431
- end
432
-
433
- context "with scopes" do
434
- background do
435
- default_scopes_exist :public
436
- optional_scopes_exist :write
437
- end
438
-
439
- scenario "resource owner authorizes the client with default scopes" do
440
- visit authorization_endpoint_url(client: @client)
441
- click_on "Authorize"
442
- access_grant_should_exist_for(@client, @resource_owner)
443
- access_grant_should_have_scopes :public
444
- end
445
-
446
- scenario "resource owner authorizes the client with required scopes" do
447
- visit authorization_endpoint_url(client: @client, scope: "public write")
448
- click_on "Authorize"
449
- access_grant_should_have_scopes :public, :write
450
- end
451
-
452
- scenario "resource owner authorizes the client with required scopes (without defaults)" do
453
- visit authorization_endpoint_url(client: @client, scope: "write")
454
- click_on "Authorize"
455
- access_grant_should_have_scopes :write
456
- end
457
-
458
- scenario "new access token matches required scopes" do
459
- visit authorization_endpoint_url(client: @client, scope: "public write")
460
- click_on "Authorize"
461
-
462
- authorization_code = Doorkeeper::AccessGrant.first.token
463
- create_access_token authorization_code, @client
464
-
465
- access_token_should_exist_for(@client, @resource_owner)
466
- access_token_should_have_scopes :public, :write
467
- end
468
-
469
- scenario "returns new token if scopes have changed" do
470
- client_is_authorized(@client, @resource_owner, scopes: "public write")
471
- visit authorization_endpoint_url(client: @client, scope: "public")
472
- click_on "Authorize"
473
-
474
- authorization_code = Doorkeeper::AccessGrant.first.token
475
- create_access_token authorization_code, @client
476
-
477
- expect(Doorkeeper::AccessToken.count).to be(2)
478
-
479
- should_have_json "access_token", Doorkeeper::AccessToken.last.token
480
- end
481
-
482
- scenario "resource owner authorizes the client with extra scopes" do
483
- client_is_authorized(@client, @resource_owner, scopes: "public")
484
- visit authorization_endpoint_url(client: @client, scope: "public write")
485
- click_on "Authorize"
486
-
487
- authorization_code = Doorkeeper::AccessGrant.first.token
488
- create_access_token authorization_code, @client
489
-
490
- expect(Doorkeeper::AccessToken.count).to be(2)
491
-
492
- should_have_json "access_token", Doorkeeper::AccessToken.last.token
493
- access_token_should_have_scopes :public, :write
494
- end
495
- end
496
- end
497
-
498
- describe "Authorization Code Flow" do
499
- before do
500
- Doorkeeper.configure do
501
- orm DOORKEEPER_ORM
502
- use_refresh_token
503
- end
504
-
505
- client_exists
506
- end
507
-
508
- context "issuing a refresh token" do
509
- before do
510
- authorization_code_exists application: @client
511
- end
512
-
513
- it "second of simultaneous client requests get an error for revoked acccess token" do
514
- authorization_code = Doorkeeper::AccessGrant.first.token
515
- allow_any_instance_of(Doorkeeper::AccessGrant)
516
- .to receive(:revoked?).and_return(false, true)
517
-
518
- post token_endpoint_url(code: authorization_code, client: @client)
519
-
520
- should_not_have_json "access_token"
521
- should_have_json "error", "invalid_grant"
522
- should_have_json "error_description", translated_error_message(:invalid_grant)
523
- end
524
- end
525
- end
@@ -1,166 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- describe "Client Credentials Request" do
6
- let(:client) { FactoryBot.create :application }
7
-
8
- context "a valid request" do
9
- it "authorizes the client and returns the token response" do
10
- headers = authorization client.uid, client.secret
11
- params = { grant_type: "client_credentials" }
12
-
13
- post "/oauth/token", params: params, headers: headers
14
-
15
- should_have_json "access_token", Doorkeeper::AccessToken.first.token
16
- should_have_json_within "expires_in", Doorkeeper.configuration.access_token_expires_in, 1
17
- should_not_have_json "scope"
18
- should_not_have_json "refresh_token"
19
-
20
- should_not_have_json "error"
21
- should_not_have_json "error_description"
22
- end
23
-
24
- context "with scopes" do
25
- before do
26
- optional_scopes_exist :write
27
- default_scopes_exist :public
28
- end
29
-
30
- it "adds the scope to the token an returns in the response" do
31
- headers = authorization client.uid, client.secret
32
- params = { grant_type: "client_credentials", scope: "write" }
33
-
34
- post "/oauth/token", params: params, headers: headers
35
-
36
- should_have_json "access_token", Doorkeeper::AccessToken.first.token
37
- should_have_json "scope", "write"
38
- end
39
-
40
- context "that are default" do
41
- it "adds the scope to the token an returns in the response" do
42
- headers = authorization client.uid, client.secret
43
- params = { grant_type: "client_credentials", scope: "public" }
44
-
45
- post "/oauth/token", params: params, headers: headers
46
-
47
- should_have_json "access_token", Doorkeeper::AccessToken.first.token
48
- should_have_json "scope", "public"
49
- end
50
- end
51
-
52
- context "that are invalid" do
53
- it "does not authorize the client and returns the error" do
54
- headers = authorization client.uid, client.secret
55
- params = { grant_type: "client_credentials", scope: "random" }
56
-
57
- post "/oauth/token", params: params, headers: headers
58
-
59
- should_have_json "error", "invalid_scope"
60
- should_have_json "error_description", translated_error_message(:invalid_scope)
61
- should_not_have_json "access_token"
62
-
63
- expect(response.status).to eq(400)
64
- end
65
- end
66
- end
67
- end
68
-
69
- context "when configured to check application supported grant flow" do
70
- before do
71
- Doorkeeper.configuration.instance_variable_set(
72
- :@allow_grant_flow_for_client,
73
- ->(_grant_flow, client) { client.name == "admin" },
74
- )
75
- end
76
-
77
- scenario "forbids the request when doesn't satisfy condition" do
78
- client.update(name: "sample app")
79
-
80
- headers = authorization client.uid, client.secret
81
- params = { grant_type: "client_credentials" }
82
-
83
- post "/oauth/token", params: params, headers: headers
84
-
85
- should_have_json "error", "unauthorized_client"
86
- should_have_json "error_description", translated_error_message(:unauthorized_client)
87
- end
88
-
89
- scenario "allows the request when satisfies condition" do
90
- client.update(name: "admin")
91
-
92
- headers = authorization client.uid, client.secret
93
- params = { grant_type: "client_credentials" }
94
-
95
- post "/oauth/token", params: params, headers: headers
96
-
97
- should_have_json "access_token", Doorkeeper::AccessToken.first.token
98
- should_have_json_within "expires_in", Doorkeeper.configuration.access_token_expires_in, 1
99
- should_not_have_json "scope"
100
- should_not_have_json "refresh_token"
101
-
102
- should_not_have_json "error"
103
- should_not_have_json "error_description"
104
- end
105
- end
106
-
107
- context "when application scopes contain some of the default scopes and no scope is passed" do
108
- before do
109
- client.update(scopes: "read write public")
110
- end
111
-
112
- it "issues new token with one default scope that are present in application scopes" do
113
- default_scopes_exist :public
114
-
115
- headers = authorization client.uid, client.secret
116
- params = { grant_type: "client_credentials" }
117
-
118
- expect do
119
- post "/oauth/token", params: params, headers: headers
120
- end.to change { Doorkeeper::AccessToken.count }.by(1)
121
-
122
- token = Doorkeeper::AccessToken.first
123
-
124
- expect(token.application_id).to eq client.id
125
- should_have_json "access_token", token.token
126
- should_have_json "scope", "public"
127
- end
128
-
129
- it "issues new token with multiple default scopes that are present in application scopes" do
130
- default_scopes_exist :public, :read, :update
131
-
132
- headers = authorization client.uid, client.secret
133
- params = { grant_type: "client_credentials" }
134
-
135
- expect do
136
- post "/oauth/token", params: params, headers: headers
137
- end.to change { Doorkeeper::AccessToken.count }.by(1)
138
-
139
- token = Doorkeeper::AccessToken.first
140
-
141
- expect(token.application_id).to eq client.id
142
- should_have_json "access_token", token.token
143
- should_have_json "scope", "public read"
144
- end
145
- end
146
-
147
- context "an invalid request" do
148
- it "does not authorize the client and returns the error" do
149
- headers = {}
150
- params = { grant_type: "client_credentials" }
151
-
152
- post "/oauth/token", params: params, headers: headers
153
-
154
- should_have_json "error", "invalid_client"
155
- should_have_json "error_description", translated_error_message(:invalid_client)
156
- should_not_have_json "access_token"
157
-
158
- expect(response.status).to eq(401)
159
- end
160
- end
161
-
162
- def authorization(username, password)
163
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials username, password
164
- { "HTTP_AUTHORIZATION" => credentials }
165
- end
166
- end