doorkeeper 5.2.2 → 5.5.4

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