doorkeeper 5.1.2 → 5.6.6

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