doorkeeper 5.4.0.rc1 → 5.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of doorkeeper might be problematic. Click here for more details.

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