doorkeeper 5.3.3 → 5.5.0.rc2

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 (233) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +125 -7
  3. data/README.md +6 -4
  4. data/app/controllers/doorkeeper/applications_controller.rb +4 -4
  5. data/app/controllers/doorkeeper/authorizations_controller.rb +46 -16
  6. data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -2
  7. data/app/controllers/doorkeeper/tokens_controller.rb +67 -22
  8. data/app/views/doorkeeper/applications/_form.html.erb +1 -1
  9. data/app/views/doorkeeper/applications/show.html.erb +35 -14
  10. data/app/views/doorkeeper/authorizations/form_post.html.erb +11 -0
  11. data/config/locales/en.yml +6 -2
  12. data/lib/doorkeeper.rb +111 -79
  13. data/lib/doorkeeper/config.rb +148 -94
  14. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  15. data/lib/doorkeeper/config/option.rb +26 -14
  16. data/lib/doorkeeper/config/validations.rb +53 -0
  17. data/lib/doorkeeper/engine.rb +1 -1
  18. data/lib/doorkeeper/grant_flow.rb +45 -0
  19. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  20. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  21. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  22. data/lib/doorkeeper/grape/helpers.rb +1 -1
  23. data/lib/doorkeeper/helpers/controller.rb +8 -4
  24. data/lib/doorkeeper/models/access_grant_mixin.rb +21 -18
  25. data/lib/doorkeeper/models/access_token_mixin.rb +110 -47
  26. data/lib/doorkeeper/models/application_mixin.rb +5 -4
  27. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  28. data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
  29. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  30. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  31. data/lib/doorkeeper/oauth/authorization/code.rb +19 -6
  32. data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
  33. data/lib/doorkeeper/oauth/authorization/token.rb +18 -16
  34. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  35. data/lib/doorkeeper/oauth/authorization_code_request.rb +17 -14
  36. data/lib/doorkeeper/oauth/base_request.rb +12 -20
  37. data/lib/doorkeeper/oauth/client.rb +1 -1
  38. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  39. data/lib/doorkeeper/oauth/client_credentials/creator.rb +27 -8
  40. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +4 -2
  41. data/lib/doorkeeper/oauth/client_credentials/validator.rb +4 -2
  42. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  43. data/lib/doorkeeper/oauth/code_request.rb +3 -3
  44. data/lib/doorkeeper/oauth/code_response.rb +22 -12
  45. data/lib/doorkeeper/oauth/error_response.rb +6 -7
  46. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -8
  47. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  48. data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -2
  49. data/lib/doorkeeper/oauth/password_access_token_request.rb +24 -7
  50. data/lib/doorkeeper/oauth/pre_authorization.rb +63 -32
  51. data/lib/doorkeeper/oauth/refresh_token_request.rb +31 -22
  52. data/lib/doorkeeper/oauth/token.rb +5 -6
  53. data/lib/doorkeeper/oauth/token_introspection.rb +4 -8
  54. data/lib/doorkeeper/oauth/token_request.rb +3 -3
  55. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  56. data/lib/doorkeeper/orm/active_record.rb +14 -7
  57. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +8 -3
  58. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +7 -3
  59. data/lib/doorkeeper/orm/active_record/mixins/application.rb +6 -3
  60. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +5 -0
  61. data/lib/doorkeeper/rails/routes.rb +14 -20
  62. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  63. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  64. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  65. data/lib/doorkeeper/request.rb +49 -12
  66. data/lib/doorkeeper/request/refresh_token.rb +2 -1
  67. data/lib/doorkeeper/request/strategy.rb +2 -2
  68. data/lib/doorkeeper/server.rb +4 -4
  69. data/lib/doorkeeper/stale_records_cleaner.rb +4 -4
  70. data/lib/doorkeeper/version.rb +3 -7
  71. data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
  72. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  73. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +3 -1
  74. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  75. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  76. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  77. data/lib/generators/doorkeeper/templates/initializer.rb +48 -10
  78. data/lib/generators/doorkeeper/templates/migration.rb.erb +14 -5
  79. metadata +30 -300
  80. data/Appraisals +0 -40
  81. data/CODE_OF_CONDUCT.md +0 -46
  82. data/CONTRIBUTING.md +0 -49
  83. data/Dangerfile +0 -67
  84. data/Dockerfile +0 -29
  85. data/Gemfile +0 -25
  86. data/NEWS.md +0 -1
  87. data/RELEASING.md +0 -11
  88. data/Rakefile +0 -28
  89. data/SECURITY.md +0 -15
  90. data/UPGRADE.md +0 -2
  91. data/bin/console +0 -16
  92. data/doorkeeper.gemspec +0 -42
  93. data/gemfiles/rails_5_0.gemfile +0 -18
  94. data/gemfiles/rails_5_1.gemfile +0 -18
  95. data/gemfiles/rails_5_2.gemfile +0 -18
  96. data/gemfiles/rails_6_0.gemfile +0 -18
  97. data/gemfiles/rails_master.gemfile +0 -18
  98. data/spec/controllers/application_metal_controller_spec.rb +0 -64
  99. data/spec/controllers/applications_controller_spec.rb +0 -274
  100. data/spec/controllers/authorizations_controller_spec.rb +0 -608
  101. data/spec/controllers/protected_resources_controller_spec.rb +0 -361
  102. data/spec/controllers/token_info_controller_spec.rb +0 -50
  103. data/spec/controllers/tokens_controller_spec.rb +0 -498
  104. data/spec/dummy/Rakefile +0 -9
  105. data/spec/dummy/app/assets/config/manifest.js +0 -2
  106. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  107. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
  108. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
  109. data/spec/dummy/app/controllers/home_controller.rb +0 -18
  110. data/spec/dummy/app/controllers/metal_controller.rb +0 -13
  111. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
  112. data/spec/dummy/app/helpers/application_helper.rb +0 -7
  113. data/spec/dummy/app/models/user.rb +0 -7
  114. data/spec/dummy/app/views/home/index.html.erb +0 -0
  115. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  116. data/spec/dummy/config.ru +0 -6
  117. data/spec/dummy/config/application.rb +0 -49
  118. data/spec/dummy/config/boot.rb +0 -7
  119. data/spec/dummy/config/database.yml +0 -15
  120. data/spec/dummy/config/environment.rb +0 -5
  121. data/spec/dummy/config/environments/development.rb +0 -31
  122. data/spec/dummy/config/environments/production.rb +0 -64
  123. data/spec/dummy/config/environments/test.rb +0 -45
  124. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
  125. data/spec/dummy/config/initializers/doorkeeper.rb +0 -166
  126. data/spec/dummy/config/initializers/secret_token.rb +0 -10
  127. data/spec/dummy/config/initializers/session_store.rb +0 -10
  128. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  129. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  130. data/spec/dummy/config/routes.rb +0 -13
  131. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  132. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  133. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
  134. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  135. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  136. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
  137. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
  138. data/spec/dummy/db/schema.rb +0 -68
  139. data/spec/dummy/public/404.html +0 -26
  140. data/spec/dummy/public/422.html +0 -26
  141. data/spec/dummy/public/500.html +0 -26
  142. data/spec/dummy/public/favicon.ico +0 -0
  143. data/spec/dummy/script/rails +0 -9
  144. data/spec/factories.rb +0 -30
  145. data/spec/generators/application_owner_generator_spec.rb +0 -28
  146. data/spec/generators/confidential_applications_generator_spec.rb +0 -29
  147. data/spec/generators/install_generator_spec.rb +0 -36
  148. data/spec/generators/migration_generator_spec.rb +0 -28
  149. data/spec/generators/pkce_generator_spec.rb +0 -28
  150. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
  151. data/spec/generators/templates/routes.rb +0 -4
  152. data/spec/generators/views_generator_spec.rb +0 -29
  153. data/spec/grape/grape_integration_spec.rb +0 -137
  154. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
  155. data/spec/lib/config_spec.rb +0 -809
  156. data/spec/lib/doorkeeper_spec.rb +0 -27
  157. data/spec/lib/models/expirable_spec.rb +0 -61
  158. data/spec/lib/models/reusable_spec.rb +0 -40
  159. data/spec/lib/models/revocable_spec.rb +0 -59
  160. data/spec/lib/models/scopes_spec.rb +0 -53
  161. data/spec/lib/models/secret_storable_spec.rb +0 -135
  162. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
  163. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -170
  164. data/spec/lib/oauth/base_request_spec.rb +0 -224
  165. data/spec/lib/oauth/base_response_spec.rb +0 -45
  166. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  167. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -134
  168. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
  169. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
  170. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
  171. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -107
  172. data/spec/lib/oauth/client_spec.rb +0 -38
  173. data/spec/lib/oauth/code_request_spec.rb +0 -46
  174. data/spec/lib/oauth/code_response_spec.rb +0 -32
  175. data/spec/lib/oauth/error_response_spec.rb +0 -64
  176. data/spec/lib/oauth/error_spec.rb +0 -21
  177. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -20
  178. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -110
  179. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
  180. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -262
  181. data/spec/lib/oauth/invalid_request_response_spec.rb +0 -73
  182. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -53
  183. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -190
  184. data/spec/lib/oauth/pre_authorization_spec.rb +0 -223
  185. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -177
  186. data/spec/lib/oauth/scopes_spec.rb +0 -146
  187. data/spec/lib/oauth/token_request_spec.rb +0 -157
  188. data/spec/lib/oauth/token_response_spec.rb +0 -84
  189. data/spec/lib/oauth/token_spec.rb +0 -156
  190. data/spec/lib/request/strategy_spec.rb +0 -54
  191. data/spec/lib/secret_storing/base_spec.rb +0 -60
  192. data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
  193. data/spec/lib/secret_storing/plain_spec.rb +0 -44
  194. data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
  195. data/spec/lib/server_spec.rb +0 -49
  196. data/spec/lib/stale_records_cleaner_spec.rb +0 -89
  197. data/spec/models/doorkeeper/access_grant_spec.rb +0 -161
  198. data/spec/models/doorkeeper/access_token_spec.rb +0 -622
  199. data/spec/models/doorkeeper/application_spec.rb +0 -482
  200. data/spec/requests/applications/applications_request_spec.rb +0 -259
  201. data/spec/requests/applications/authorized_applications_spec.rb +0 -32
  202. data/spec/requests/endpoints/authorization_spec.rb +0 -91
  203. data/spec/requests/endpoints/token_spec.rb +0 -75
  204. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -79
  205. data/spec/requests/flows/authorization_code_spec.rb +0 -525
  206. data/spec/requests/flows/client_credentials_spec.rb +0 -166
  207. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -46
  208. data/spec/requests/flows/implicit_grant_spec.rb +0 -91
  209. data/spec/requests/flows/password_spec.rb +0 -316
  210. data/spec/requests/flows/refresh_token_spec.rb +0 -233
  211. data/spec/requests/flows/revoke_token_spec.rb +0 -157
  212. data/spec/requests/flows/skip_authorization_spec.rb +0 -66
  213. data/spec/requests/protected_resources/metal_spec.rb +0 -16
  214. data/spec/requests/protected_resources/private_api_spec.rb +0 -83
  215. data/spec/routing/custom_controller_routes_spec.rb +0 -133
  216. data/spec/routing/default_routes_spec.rb +0 -41
  217. data/spec/routing/scoped_routes_spec.rb +0 -47
  218. data/spec/spec_helper.rb +0 -54
  219. data/spec/spec_helper_integration.rb +0 -4
  220. data/spec/support/dependencies/factory_bot.rb +0 -4
  221. data/spec/support/doorkeeper_rspec.rb +0 -22
  222. data/spec/support/helpers/access_token_request_helper.rb +0 -13
  223. data/spec/support/helpers/authorization_request_helper.rb +0 -43
  224. data/spec/support/helpers/config_helper.rb +0 -11
  225. data/spec/support/helpers/model_helper.rb +0 -78
  226. data/spec/support/helpers/request_spec_helper.rb +0 -110
  227. data/spec/support/helpers/url_helper.rb +0 -62
  228. data/spec/support/orm/active_record.rb +0 -5
  229. data/spec/support/shared/controllers_shared_context.rb +0 -133
  230. data/spec/support/shared/hashing_shared_context.rb +0 -36
  231. data/spec/support/shared/models_shared_examples.rb +0 -54
  232. data/spec/validators/redirect_uri_validator_spec.rb +0 -183
  233. data/spec/version/version_spec.rb +0 -17
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- feature "Authorization Code Flow Errors" do
6
- let(:client_params) { {} }
7
- background do
8
- default_scopes_exist :default
9
- config_is_set(:authenticate_resource_owner) { User.first || redirect_to("/sign_in") }
10
- client_exists client_params
11
- create_resource_owner
12
- sign_in
13
- end
14
-
15
- after do
16
- access_grant_should_not_exist
17
- end
18
-
19
- context "with a client trying to xss resource owner" do
20
- let(:client_name) { "<div id='xss'>XSS</div>" }
21
- let(:client_params) { { name: client_name } }
22
- scenario "resource owner visit authorization endpoint" do
23
- visit authorization_endpoint_url(client: @client)
24
- expect(page).not_to have_css("#xss")
25
- end
26
- end
27
-
28
- context "when access was denied" do
29
- scenario "redirects with error" do
30
- visit authorization_endpoint_url(client: @client)
31
- click_on "Deny"
32
-
33
- i_should_be_on_client_callback @client
34
- url_should_not_have_param "code"
35
- url_should_have_param "error", "access_denied"
36
- url_should_have_param "error_description", translated_error_message(:access_denied)
37
- end
38
-
39
- scenario "redirects with state parameter" do
40
- visit authorization_endpoint_url(client: @client, state: "return-this")
41
- click_on "Deny"
42
-
43
- i_should_be_on_client_callback @client
44
- url_should_not_have_param "code"
45
- url_should_have_param "state", "return-this"
46
- end
47
- end
48
- end
49
-
50
- describe "Authorization Code Flow Errors", "after authorization" do
51
- before do
52
- client_exists
53
- authorization_code_exists application: @client
54
- end
55
-
56
- it "returns :invalid_grant error when posting an already revoked grant code" do
57
- # First successful request
58
- post token_endpoint_url(code: @authorization.token, client: @client)
59
-
60
- # Second attempt with same token
61
- expect do
62
- post token_endpoint_url(code: @authorization.token, client: @client)
63
- end.to_not(change { Doorkeeper::AccessToken.count })
64
-
65
- should_not_have_json "access_token"
66
- should_have_json "error", "invalid_grant"
67
- should_have_json "error_description", translated_error_message("invalid_grant")
68
- end
69
-
70
- it "returns :invalid_grant error for invalid grant code" do
71
- post token_endpoint_url(code: "invalid", client: @client)
72
-
73
- access_token_should_not_exist
74
-
75
- should_not_have_json "access_token"
76
- should_have_json "error", "invalid_grant"
77
- should_have_json "error_description", translated_error_message("invalid_grant")
78
- end
79
- end
@@ -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