doorkeeper 5.2.2 → 5.5.4

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

Potentially problematic release.


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

Files changed (260) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +198 -3
  3. data/README.md +28 -20
  4. data/app/controllers/doorkeeper/application_controller.rb +3 -2
  5. data/app/controllers/doorkeeper/application_metal_controller.rb +2 -2
  6. data/app/controllers/doorkeeper/applications_controller.rb +7 -8
  7. data/app/controllers/doorkeeper/authorizations_controller.rb +48 -18
  8. data/app/controllers/doorkeeper/authorized_applications_controller.rb +6 -6
  9. data/app/controllers/doorkeeper/token_info_controller.rb +12 -2
  10. data/app/controllers/doorkeeper/tokens_controller.rb +70 -25
  11. data/app/helpers/doorkeeper/dashboard_helper.rb +1 -1
  12. data/app/views/doorkeeper/applications/_form.html.erb +1 -1
  13. data/app/views/doorkeeper/applications/show.html.erb +35 -14
  14. data/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
  15. data/app/views/doorkeeper/authorizations/new.html.erb +2 -0
  16. data/config/locales/en.yml +9 -2
  17. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  18. data/lib/doorkeeper/config/option.rb +26 -14
  19. data/lib/doorkeeper/config/validations.rb +53 -0
  20. data/lib/doorkeeper/config.rb +214 -122
  21. data/lib/doorkeeper/engine.rb +1 -1
  22. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  23. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  24. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  25. data/lib/doorkeeper/grant_flow.rb +45 -0
  26. data/lib/doorkeeper/grape/helpers.rb +2 -2
  27. data/lib/doorkeeper/helpers/controller.rb +18 -12
  28. data/lib/doorkeeper/models/access_grant_mixin.rb +23 -19
  29. data/lib/doorkeeper/models/access_token_mixin.rb +157 -55
  30. data/lib/doorkeeper/models/application_mixin.rb +8 -7
  31. data/lib/doorkeeper/models/concerns/expirable.rb +1 -1
  32. data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
  33. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  34. data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
  35. data/lib/doorkeeper/models/concerns/revocable.rb +1 -28
  36. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  37. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  38. data/lib/doorkeeper/oauth/authorization/code.rb +22 -9
  39. data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
  40. data/lib/doorkeeper/oauth/authorization/token.rb +23 -18
  41. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  42. data/lib/doorkeeper/oauth/authorization_code_request.rb +30 -20
  43. data/lib/doorkeeper/oauth/base_request.rb +19 -23
  44. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  45. data/lib/doorkeeper/oauth/client.rb +8 -9
  46. data/lib/doorkeeper/oauth/client_credentials/creator.rb +38 -12
  47. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +10 -8
  48. data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +7 -5
  49. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  50. data/lib/doorkeeper/oauth/code_request.rb +4 -4
  51. data/lib/doorkeeper/oauth/code_response.rb +24 -14
  52. data/lib/doorkeeper/oauth/error.rb +1 -1
  53. data/lib/doorkeeper/oauth/error_response.rb +10 -11
  54. data/lib/doorkeeper/oauth/forbidden_token_response.rb +2 -1
  55. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +8 -12
  56. data/lib/doorkeeper/oauth/helpers/unique_token.rb +10 -7
  57. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +1 -19
  58. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  59. data/lib/doorkeeper/oauth/invalid_request_response.rb +3 -3
  60. data/lib/doorkeeper/oauth/invalid_token_response.rb +7 -4
  61. data/lib/doorkeeper/oauth/password_access_token_request.rb +28 -10
  62. data/lib/doorkeeper/oauth/pre_authorization.rb +73 -37
  63. data/lib/doorkeeper/oauth/refresh_token_request.rb +35 -26
  64. data/lib/doorkeeper/oauth/token.rb +6 -7
  65. data/lib/doorkeeper/oauth/token_introspection.rb +12 -16
  66. data/lib/doorkeeper/oauth/token_request.rb +3 -3
  67. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  68. data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
  69. data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
  70. data/lib/doorkeeper/orm/active_record/application.rb +5 -95
  71. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +69 -0
  72. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +60 -0
  73. data/lib/doorkeeper/orm/active_record/mixins/application.rb +199 -0
  74. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +8 -3
  75. data/lib/doorkeeper/orm/active_record.rb +5 -7
  76. data/lib/doorkeeper/rails/helpers.rb +4 -4
  77. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  78. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  79. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  80. data/lib/doorkeeper/rails/routes.rb +17 -25
  81. data/lib/doorkeeper/rake/db.rake +6 -6
  82. data/lib/doorkeeper/rake/setup.rake +5 -0
  83. data/lib/doorkeeper/request/authorization_code.rb +3 -3
  84. data/lib/doorkeeper/request/client_credentials.rb +2 -2
  85. data/lib/doorkeeper/request/password.rb +3 -2
  86. data/lib/doorkeeper/request/refresh_token.rb +5 -4
  87. data/lib/doorkeeper/request/strategy.rb +2 -2
  88. data/lib/doorkeeper/request.rb +49 -12
  89. data/lib/doorkeeper/server.rb +5 -5
  90. data/lib/doorkeeper/stale_records_cleaner.rb +4 -4
  91. data/lib/doorkeeper/version.rb +2 -6
  92. data/lib/doorkeeper.rb +112 -81
  93. data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
  94. data/lib/generators/doorkeeper/confidential_applications_generator.rb +2 -2
  95. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  96. data/lib/generators/doorkeeper/migration_generator.rb +1 -1
  97. data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
  98. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +2 -2
  99. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +3 -1
  100. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  101. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  102. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  103. data/lib/generators/doorkeeper/templates/initializer.rb +99 -14
  104. data/lib/generators/doorkeeper/templates/migration.rb.erb +14 -5
  105. metadata +37 -306
  106. data/Appraisals +0 -40
  107. data/CODE_OF_CONDUCT.md +0 -46
  108. data/CONTRIBUTING.md +0 -49
  109. data/Dangerfile +0 -67
  110. data/Dockerfile +0 -29
  111. data/Gemfile +0 -25
  112. data/NEWS.md +0 -1
  113. data/RELEASING.md +0 -11
  114. data/Rakefile +0 -28
  115. data/SECURITY.md +0 -15
  116. data/UPGRADE.md +0 -2
  117. data/bin/console +0 -16
  118. data/doorkeeper.gemspec +0 -42
  119. data/gemfiles/rails_5_0.gemfile +0 -18
  120. data/gemfiles/rails_5_1.gemfile +0 -18
  121. data/gemfiles/rails_5_2.gemfile +0 -18
  122. data/gemfiles/rails_6_0.gemfile +0 -18
  123. data/gemfiles/rails_master.gemfile +0 -18
  124. data/spec/controllers/application_metal_controller_spec.rb +0 -64
  125. data/spec/controllers/applications_controller_spec.rb +0 -273
  126. data/spec/controllers/authorizations_controller_spec.rb +0 -608
  127. data/spec/controllers/protected_resources_controller_spec.rb +0 -353
  128. data/spec/controllers/token_info_controller_spec.rb +0 -50
  129. data/spec/controllers/tokens_controller_spec.rb +0 -498
  130. data/spec/dummy/Rakefile +0 -9
  131. data/spec/dummy/app/assets/config/manifest.js +0 -2
  132. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  133. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
  134. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
  135. data/spec/dummy/app/controllers/home_controller.rb +0 -18
  136. data/spec/dummy/app/controllers/metal_controller.rb +0 -13
  137. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
  138. data/spec/dummy/app/helpers/application_helper.rb +0 -7
  139. data/spec/dummy/app/models/user.rb +0 -7
  140. data/spec/dummy/app/views/home/index.html.erb +0 -0
  141. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  142. data/spec/dummy/config/application.rb +0 -49
  143. data/spec/dummy/config/boot.rb +0 -7
  144. data/spec/dummy/config/database.yml +0 -15
  145. data/spec/dummy/config/environment.rb +0 -5
  146. data/spec/dummy/config/environments/development.rb +0 -31
  147. data/spec/dummy/config/environments/production.rb +0 -64
  148. data/spec/dummy/config/environments/test.rb +0 -45
  149. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
  150. data/spec/dummy/config/initializers/doorkeeper.rb +0 -166
  151. data/spec/dummy/config/initializers/secret_token.rb +0 -10
  152. data/spec/dummy/config/initializers/session_store.rb +0 -10
  153. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  154. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  155. data/spec/dummy/config/routes.rb +0 -13
  156. data/spec/dummy/config.ru +0 -6
  157. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  158. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  159. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
  160. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  161. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  162. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
  163. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
  164. data/spec/dummy/db/schema.rb +0 -68
  165. data/spec/dummy/public/404.html +0 -26
  166. data/spec/dummy/public/422.html +0 -26
  167. data/spec/dummy/public/500.html +0 -26
  168. data/spec/dummy/public/favicon.ico +0 -0
  169. data/spec/dummy/script/rails +0 -9
  170. data/spec/factories.rb +0 -30
  171. data/spec/generators/application_owner_generator_spec.rb +0 -28
  172. data/spec/generators/confidential_applications_generator_spec.rb +0 -29
  173. data/spec/generators/install_generator_spec.rb +0 -36
  174. data/spec/generators/migration_generator_spec.rb +0 -28
  175. data/spec/generators/pkce_generator_spec.rb +0 -28
  176. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
  177. data/spec/generators/templates/routes.rb +0 -4
  178. data/spec/generators/views_generator_spec.rb +0 -29
  179. data/spec/grape/grape_integration_spec.rb +0 -137
  180. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
  181. data/spec/lib/config_spec.rb +0 -739
  182. data/spec/lib/doorkeeper_spec.rb +0 -27
  183. data/spec/lib/models/expirable_spec.rb +0 -61
  184. data/spec/lib/models/reusable_spec.rb +0 -40
  185. data/spec/lib/models/revocable_spec.rb +0 -59
  186. data/spec/lib/models/scopes_spec.rb +0 -53
  187. data/spec/lib/models/secret_storable_spec.rb +0 -135
  188. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
  189. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -168
  190. data/spec/lib/oauth/base_request_spec.rb +0 -222
  191. data/spec/lib/oauth/base_response_spec.rb +0 -47
  192. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  193. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -97
  194. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
  195. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
  196. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -29
  197. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -109
  198. data/spec/lib/oauth/client_spec.rb +0 -38
  199. data/spec/lib/oauth/code_request_spec.rb +0 -46
  200. data/spec/lib/oauth/code_response_spec.rb +0 -36
  201. data/spec/lib/oauth/error_response_spec.rb +0 -66
  202. data/spec/lib/oauth/error_spec.rb +0 -23
  203. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -22
  204. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -98
  205. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
  206. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -262
  207. data/spec/lib/oauth/invalid_request_response_spec.rb +0 -75
  208. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -55
  209. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -192
  210. data/spec/lib/oauth/pre_authorization_spec.rb +0 -225
  211. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -178
  212. data/spec/lib/oauth/scopes_spec.rb +0 -148
  213. data/spec/lib/oauth/token_request_spec.rb +0 -153
  214. data/spec/lib/oauth/token_response_spec.rb +0 -86
  215. data/spec/lib/oauth/token_spec.rb +0 -158
  216. data/spec/lib/request/strategy_spec.rb +0 -54
  217. data/spec/lib/secret_storing/base_spec.rb +0 -60
  218. data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
  219. data/spec/lib/secret_storing/plain_spec.rb +0 -44
  220. data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
  221. data/spec/lib/server_spec.rb +0 -49
  222. data/spec/lib/stale_records_cleaner_spec.rb +0 -89
  223. data/spec/models/doorkeeper/access_grant_spec.rb +0 -163
  224. data/spec/models/doorkeeper/access_token_spec.rb +0 -622
  225. data/spec/models/doorkeeper/application_spec.rb +0 -377
  226. data/spec/requests/applications/applications_request_spec.rb +0 -259
  227. data/spec/requests/applications/authorized_applications_spec.rb +0 -32
  228. data/spec/requests/endpoints/authorization_spec.rb +0 -89
  229. data/spec/requests/endpoints/token_spec.rb +0 -75
  230. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -79
  231. data/spec/requests/flows/authorization_code_spec.rb +0 -513
  232. data/spec/requests/flows/client_credentials_spec.rb +0 -166
  233. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -46
  234. data/spec/requests/flows/implicit_grant_spec.rb +0 -91
  235. data/spec/requests/flows/password_spec.rb +0 -296
  236. data/spec/requests/flows/refresh_token_spec.rb +0 -233
  237. data/spec/requests/flows/revoke_token_spec.rb +0 -151
  238. data/spec/requests/flows/skip_authorization_spec.rb +0 -66
  239. data/spec/requests/protected_resources/metal_spec.rb +0 -16
  240. data/spec/requests/protected_resources/private_api_spec.rb +0 -83
  241. data/spec/routing/custom_controller_routes_spec.rb +0 -133
  242. data/spec/routing/default_routes_spec.rb +0 -41
  243. data/spec/routing/scoped_routes_spec.rb +0 -47
  244. data/spec/spec_helper.rb +0 -57
  245. data/spec/spec_helper_integration.rb +0 -4
  246. data/spec/support/dependencies/factory_bot.rb +0 -4
  247. data/spec/support/doorkeeper_rspec.rb +0 -22
  248. data/spec/support/helpers/access_token_request_helper.rb +0 -13
  249. data/spec/support/helpers/authorization_request_helper.rb +0 -43
  250. data/spec/support/helpers/config_helper.rb +0 -11
  251. data/spec/support/helpers/model_helper.rb +0 -78
  252. data/spec/support/helpers/request_spec_helper.rb +0 -110
  253. data/spec/support/helpers/url_helper.rb +0 -62
  254. data/spec/support/http_method_shim.rb +0 -29
  255. data/spec/support/orm/active_record.rb +0 -5
  256. data/spec/support/shared/controllers_shared_context.rb +0 -123
  257. data/spec/support/shared/hashing_shared_context.rb +0 -36
  258. data/spec/support/shared/models_shared_examples.rb +0 -54
  259. data/spec/validators/redirect_uri_validator_spec.rb +0 -183
  260. data/spec/version/version_spec.rb +0 -17
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Doorkeeper
4
4
  class TokensController < Doorkeeper::ApplicationMetalController
5
+ before_action :validate_presence_of_client, only: [:revoke]
6
+
5
7
  def create
6
8
  headers.merge!(authorize_response.headers)
7
9
  render json: authorize_response.body,
@@ -10,16 +12,17 @@ module Doorkeeper
10
12
  handle_token_exception(e)
11
13
  end
12
14
 
13
- # OAuth 2.0 Token Revocation - http://tools.ietf.org/html/rfc7009
15
+ # OAuth 2.0 Token Revocation - https://datatracker.ietf.org/doc/html/rfc7009
14
16
  def revoke
15
- # The authorization server, if applicable, first authenticates the client
16
- # and checks its ownership of the provided token.
17
- #
18
- # Doorkeeper does not use the token_type_hint logic described in the
19
- # RFC 7009 due to the refresh token implementation that is a field in
20
- # the access token model.
21
-
22
- if authorized?
17
+ # The authorization server responds with HTTP status code 200 if the client
18
+ # submitted an invalid token or the token has been revoked successfully.
19
+ if token.blank?
20
+ render json: {}, status: 200
21
+ # The authorization server validates [...] and whether the token
22
+ # was issued to the client making the revocation request. If this
23
+ # validation fails, the request is refused and the client is informed
24
+ # of the error by the authorization server as described below.
25
+ elsif authorized?
23
26
  revoke_token
24
27
  render json: {}, status: 200
25
28
  else
@@ -41,9 +44,45 @@ module Doorkeeper
41
44
 
42
45
  private
43
46
 
47
+ def validate_presence_of_client
48
+ return if Doorkeeper.config.skip_client_authentication_for_password_grant
49
+
50
+ # @see 2.1. Revocation Request
51
+ #
52
+ # The client constructs the request by including the following
53
+ # parameters using the "application/x-www-form-urlencoded" format in
54
+ # the HTTP request entity-body:
55
+ # token REQUIRED.
56
+ # token_type_hint OPTIONAL.
57
+ #
58
+ # The client also includes its authentication credentials as described
59
+ # in Section 2.3. of [RFC6749].
60
+ #
61
+ # The authorization server first validates the client credentials (in
62
+ # case of a confidential client) and then verifies whether the token
63
+ # was issued to the client making the revocation request.
64
+ return if server.client
65
+
66
+ # If this validation [client credentials / token ownership] fails, the request is
67
+ # refused and the client is informed of the error by the authorization server as
68
+ # described below.
69
+ #
70
+ # @see 2.2.1. Error Response
71
+ #
72
+ # The error presentation conforms to the definition in Section 5.2 of [RFC6749].
73
+ render json: revocation_error_response, status: :forbidden
74
+ end
75
+
44
76
  # OAuth 2.0 Section 2.1 defines two client types, "public" & "confidential".
45
- # Public clients (as per RFC 7009) do not require authentication whereas
46
- # confidential clients must be authenticated for their token revocation.
77
+ #
78
+ # RFC7009
79
+ # Section 5. Security Considerations
80
+ # A malicious client may attempt to guess valid tokens on this endpoint
81
+ # by making revocation requests against potential token strings.
82
+ # According to this specification, a client's request must contain a
83
+ # valid client_id, in the case of a public client, or valid client
84
+ # credentials, in the case of a confidential client. The token being
85
+ # revoked must also belong to the requesting client.
47
86
  #
48
87
  # Once a confidential client is authenticated, it must be authorized to
49
88
  # revoke the provided access or refresh token. This ensures one client
@@ -55,18 +94,16 @@ module Doorkeeper
55
94
  # types, they set the application_id as null (since the claim cannot be
56
95
  # verified).
57
96
  #
58
- # https://tools.ietf.org/html/rfc6749#section-2.1
59
- # https://tools.ietf.org/html/rfc7009
97
+ # https://datatracker.ietf.org/doc/html/rfc6749#section-2.1
98
+ # https://datatracker.ietf.org/doc/html/rfc7009
60
99
  def authorized?
61
- return unless token.present?
62
-
63
- # Client is confidential, therefore client authentication & authorization
64
- # is required
100
+ # Token belongs to specific client, so we need to check if
101
+ # authenticated client could access it.
65
102
  if token.application_id? && token.application.confidential?
66
103
  # We authorize client by checking token's application
67
104
  server.client && server.client.application == token.application
68
105
  else
69
- # Client is public, authentication unnecessary
106
+ # Token was issued without client, authorization unnecessary
70
107
  true
71
108
  end
72
109
  end
@@ -78,9 +115,12 @@ module Doorkeeper
78
115
  token.revoke if token&.accessible?
79
116
  end
80
117
 
118
+ # Doorkeeper does not use the token_type_hint logic described in the
119
+ # RFC 7009 due to the refresh token implementation that is a field in
120
+ # the access token model.
81
121
  def token
82
- @token ||= AccessToken.by_token(params["token"]) ||
83
- AccessToken.by_refresh_token(params["token"])
122
+ @token ||= Doorkeeper.config.access_token_model.by_token(params["token"]) ||
123
+ Doorkeeper.config.access_token_model.by_refresh_token(params["token"])
84
124
  end
85
125
 
86
126
  def strategy
@@ -91,17 +131,22 @@ module Doorkeeper
91
131
  @authorize_response ||= begin
92
132
  before_successful_authorization
93
133
  auth = strategy.authorize
94
- after_successful_authorization unless auth.is_a?(Doorkeeper::OAuth::ErrorResponse)
134
+ context = build_context(auth: auth)
135
+ after_successful_authorization(context) unless auth.is_a?(Doorkeeper::OAuth::ErrorResponse)
95
136
  auth
96
137
  end
97
138
  end
98
139
 
99
- def after_successful_authorization
100
- Doorkeeper.configuration.after_successful_authorization.call(self)
140
+ def build_context(**attributes)
141
+ Doorkeeper::OAuth::Hooks::Context.new(**attributes)
142
+ end
143
+
144
+ def before_successful_authorization(context = nil)
145
+ Doorkeeper.config.before_successful_authorization.call(self, context)
101
146
  end
102
147
 
103
- def before_successful_authorization
104
- Doorkeeper.configuration.before_successful_authorization.call(self)
148
+ def after_successful_authorization(context)
149
+ Doorkeeper.config.after_successful_authorization.call(self, context)
105
150
  end
106
151
 
107
152
  def revocation_error_response
@@ -6,7 +6,7 @@ module Doorkeeper
6
6
  return if object.errors[method].blank?
7
7
 
8
8
  output = object.errors[method].map do |msg|
9
- content_tag(:span, class: "form-text") do
9
+ content_tag(:span, class: "invalid-feedback") do
10
10
  msg.capitalize
11
11
  end
12
12
  end
@@ -1,4 +1,4 @@
1
- <%= form_for application, url: doorkeeper_submit_path(application), html: { role: 'form' } do |f| %>
1
+ <%= form_for application, url: doorkeeper_submit_path(application), as: :doorkeeper_application, html: { role: 'form' } do |f| %>
2
2
  <% if application.errors.any? %>
3
3
  <div class="alert alert-danger" data-alert><p><%= t('doorkeeper.applications.form.error') %></p></div>
4
4
  <% end %>
@@ -8,28 +8,49 @@
8
8
  <p><code class="bg-light" id="application_id"><%= @application.uid %></code></p>
9
9
 
10
10
  <h4><%= t('.secret') %>:</h4>
11
- <p><code class="bg-light" id="secret"><%= flash[:application_secret].presence || @application.plaintext_secret %></code></p>
11
+ <p>
12
+ <code class="bg-light" id="secret">
13
+ <% secret = flash[:application_secret].presence || @application.plaintext_secret %>
14
+ <% if secret.blank? && Doorkeeper.config.application_secret_hashed? %>
15
+ <span class="bg-light font-italic text-uppercase text-muted"><%= t('.secret_hashed') %></span>
16
+ <% else %>
17
+ <%= secret %>
18
+ <% end %>
19
+ </code>
20
+ </p>
12
21
 
13
22
  <h4><%= t('.scopes') %>:</h4>
14
- <p><code class="bg-light" id="scopes"><%= @application.scopes.presence || raw('&nbsp;') %></code></p>
23
+ <p>
24
+ <code class="bg-light" id="scopes">
25
+ <% if @application.scopes.present? %>
26
+ <%= @application.scopes %>
27
+ <% else %>
28
+ <span class="bg-light font-italic text-uppercase text-muted"><%= t('.not_defined') %></span>
29
+ <% end %>
30
+ </code>
31
+ </p>
15
32
 
16
33
  <h4><%= t('.confidential') %>:</h4>
17
34
  <p><code class="bg-light" id="confidential"><%= @application.confidential? %></code></p>
18
35
 
19
36
  <h4><%= t('.callback_urls') %>:</h4>
20
37
 
21
- <table>
22
- <% @application.redirect_uri.split.each do |uri| %>
23
- <tr>
24
- <td>
25
- <code class="bg-light"><%= uri %></code>
26
- </td>
27
- <td>
28
- <%= link_to t('doorkeeper.applications.buttons.authorize'), oauth_authorization_path(client_id: @application.uid, redirect_uri: uri, response_type: 'code', scope: @application.scopes), class: 'btn btn-success', target: '_blank' %>
29
- </td>
30
- </tr>
31
- <% end %>
32
- </table>
38
+ <% if @application.redirect_uri.present? %>
39
+ <table>
40
+ <% @application.redirect_uri.split.each do |uri| %>
41
+ <tr>
42
+ <td>
43
+ <code class="bg-light"><%= uri %></code>
44
+ </td>
45
+ <td>
46
+ <%= link_to t('doorkeeper.applications.buttons.authorize'), oauth_authorization_path(client_id: @application.uid, redirect_uri: uri, response_type: 'code', scope: @application.scopes), class: 'btn btn-success', target: '_blank' %>
47
+ </td>
48
+ </tr>
49
+ <% end %>
50
+ </table>
51
+ <% else %>
52
+ <span class="bg-light font-italic text-uppercase text-muted"><%= t('.not_defined') %></span>
53
+ <% end %>
33
54
  </div>
34
55
 
35
56
  <div class="col-md-4">
@@ -0,0 +1,15 @@
1
+ <header class="page-header">
2
+ <h1><%= t('.title') %></h1>
3
+ </header>
4
+
5
+ <%= form_tag @pre_auth.redirect_uri, method: :post, name: :redirect_form, authenticity_token: false do %>
6
+ <% @authorize_response.body.compact.each do |key, value| %>
7
+ <%= hidden_field_tag key, value %>
8
+ <% end %>
9
+ <% end %>
10
+
11
+ <script>
12
+ window.onload = function () {
13
+ document.forms['redirect_form'].submit();
14
+ };
15
+ </script>
@@ -25,6 +25,7 @@
25
25
  <%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri %>
26
26
  <%= hidden_field_tag :state, @pre_auth.state %>
27
27
  <%= hidden_field_tag :response_type, @pre_auth.response_type %>
28
+ <%= hidden_field_tag :response_mode, @pre_auth.response_mode %>
28
29
  <%= hidden_field_tag :scope, @pre_auth.scope %>
29
30
  <%= hidden_field_tag :code_challenge, @pre_auth.code_challenge %>
30
31
  <%= hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method %>
@@ -35,6 +36,7 @@
35
36
  <%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri %>
36
37
  <%= hidden_field_tag :state, @pre_auth.state %>
37
38
  <%= hidden_field_tag :response_type, @pre_auth.response_type %>
39
+ <%= hidden_field_tag :response_mode, @pre_auth.response_mode %>
38
40
  <%= hidden_field_tag :scope, @pre_auth.scope %>
39
41
  <%= hidden_field_tag :code_challenge, @pre_auth.code_challenge %>
40
42
  <%= hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method %>
@@ -51,12 +51,14 @@ en:
51
51
  title: 'New Application'
52
52
  show:
53
53
  title: 'Application: %{name}'
54
- application_id: 'Application UID'
54
+ application_id: 'UID'
55
55
  secret: 'Secret'
56
+ secret_hashed: 'Secret hashed'
56
57
  scopes: 'Scopes'
57
58
  confidential: 'Confidential'
58
59
  callback_urls: 'Callback urls'
59
60
  actions: 'Actions'
61
+ not_defined: 'Not defined'
60
62
 
61
63
  authorizations:
62
64
  buttons:
@@ -70,6 +72,8 @@ en:
70
72
  able_to: 'This application will be able to'
71
73
  show:
72
74
  title: 'Authorization code'
75
+ form_post:
76
+ title: 'Submit this form'
73
77
 
74
78
  authorized_applications:
75
79
  confirmations:
@@ -91,7 +95,6 @@ en:
91
95
  invalid_request:
92
96
  unknown: 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
93
97
  missing_param: 'Missing required parameter: %{value}.'
94
- not_support_pkce: 'Invalid code_verifier parameter. Server does not support pkce.'
95
98
  request_not_authorized: 'Request need to be authorized. Required parameter for authorizing request is missing or invalid.'
96
99
  invalid_redirect_uri: "The requested redirect uri is malformed or doesn't match client redirect URI."
97
100
  unauthorized_client: 'The client is not authorized to perform this request using this method.'
@@ -108,6 +111,7 @@ en:
108
111
 
109
112
  # Access grant errors
110
113
  unsupported_response_type: 'The authorization server does not support this response type.'
114
+ unsupported_response_mode: 'The authorization server does not support this response mode.'
111
115
 
112
116
  # Access token errors
113
117
  invalid_client: 'Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method.'
@@ -121,6 +125,9 @@ en:
121
125
  revoke:
122
126
  unauthorized: "You are not authorized to revoke this token"
123
127
 
128
+ forbidden_token:
129
+ missing_scope: 'Access to this resource requires scope "%{oauth_scopes}".'
130
+
124
131
  flash:
125
132
  applications:
126
133
  create:
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ class Config
5
+ # Abstract base class for Doorkeeper and it's extensions configuration
6
+ # builder. Instantiates and validates gem configuration.
7
+ #
8
+ class AbstractBuilder
9
+ attr_reader :config
10
+
11
+ # @param [Class] config class
12
+ #
13
+ def initialize(config = Config.new, &block)
14
+ @config = config
15
+ instance_eval(&block)
16
+ end
17
+
18
+ # Builds and validates configuration.
19
+ #
20
+ # @return [Doorkeeper::Config] config instance
21
+ #
22
+ def build
23
+ @config.validate! if @config.respond_to?(:validate!)
24
+ @config
25
+ end
26
+ end
27
+ end
28
+ end
@@ -36,22 +36,27 @@ module Doorkeeper
36
36
  attribute = options[:as] || name
37
37
  attribute_builder = options[:builder_class]
38
38
 
39
- Builder.instance_eval do
40
- remove_method name if method_defined?(name)
41
- if options[:deprecated]
42
- define_method name do |*_, &_|
43
- Kernel.warn "[DOORKEEPER] #{name} has been deprecated and will soon be removed"
44
- end
45
- else
46
- define_method name do |*args, &block|
47
- value = if attribute_builder
48
- attribute_builder.new(&block).build
49
- else
50
- block || args.first
51
- end
39
+ builder_class.instance_eval do
40
+ if method_defined?(name)
41
+ Kernel.warn "[DOORKEEPER] Option #{name} already defined and will be overridden"
42
+ remove_method name
43
+ end
52
44
 
53
- @config.instance_variable_set(:"@#{attribute}", value)
45
+ define_method name do |*args, &block|
46
+ if (deprecation_opts = options[:deprecated])
47
+ warning = "[DOORKEEPER] #{name} has been deprecated and will soon be removed"
48
+ warning = "#{warning}\n#{deprecation_opts.fetch(:message)}" if deprecation_opts.is_a?(Hash)
49
+
50
+ Kernel.warn(warning)
54
51
  end
52
+
53
+ value = if attribute_builder
54
+ attribute_builder.new(&block).build
55
+ else
56
+ block || args.first
57
+ end
58
+
59
+ @config.instance_variable_set(:"@#{attribute}", value)
55
60
  end
56
61
  end
57
62
 
@@ -65,6 +70,13 @@ module Doorkeeper
65
70
 
66
71
  public attribute
67
72
  end
73
+
74
+ def self.extended(base)
75
+ return if base.respond_to?(:builder_class)
76
+
77
+ raise Doorkeeper::MissingConfigurationBuilderClass, "Define `self.builder_class` method " \
78
+ "for #{base} that returns your custom Builder class to use options DSL!"
79
+ end
68
80
  end
69
81
  end
70
82
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ class Config
5
+ # Doorkeeper configuration validator.
6
+ #
7
+ module Validations
8
+ # Validates configuration options to be set properly.
9
+ #
10
+ def validate!
11
+ validate_reuse_access_token_value
12
+ validate_token_reuse_limit
13
+ validate_secret_strategies
14
+ end
15
+
16
+ private
17
+
18
+ # Determine whether +reuse_access_token+ and a non-restorable
19
+ # +token_secret_strategy+ have both been activated.
20
+ #
21
+ # In that case, disable reuse_access_token value and warn the user.
22
+ def validate_reuse_access_token_value
23
+ strategy = token_secret_strategy
24
+ return if !reuse_access_token || strategy.allows_restoring_secrets?
25
+
26
+ ::Rails.logger.warn(
27
+ "You have configured both reuse_access_token " \
28
+ "AND strategy strategy '#{strategy}' that cannot restore tokens. " \
29
+ "This combination is unsupported. reuse_access_token will be disabled",
30
+ )
31
+ @reuse_access_token = false
32
+ end
33
+
34
+ # Validate that the provided strategies are valid for
35
+ # tokens and applications
36
+ def validate_secret_strategies
37
+ token_secret_strategy.validate_for(:token)
38
+ application_secret_strategy.validate_for(:application)
39
+ end
40
+
41
+ def validate_token_reuse_limit
42
+ return if !reuse_access_token ||
43
+ (token_reuse_limit > 0 && token_reuse_limit <= 100)
44
+
45
+ ::Rails.logger.warn(
46
+ "You have configured an invalid value for token_reuse_limit option. " \
47
+ "It will be set to default 100",
48
+ )
49
+ @token_reuse_limit = 100
50
+ end
51
+ end
52
+ end
53
+ end