doorkeeper 5.4.0 → 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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -9
  3. data/app/controllers/doorkeeper/authorizations_controller.rb +16 -5
  4. data/app/controllers/doorkeeper/tokens_controller.rb +34 -26
  5. data/app/views/doorkeeper/applications/show.html.erb +16 -12
  6. data/app/views/doorkeeper/authorizations/form_post.html.erb +11 -0
  7. data/config/locales/en.yml +3 -1
  8. data/lib/doorkeeper/config/option.rb +1 -3
  9. data/lib/doorkeeper/config/validations.rb +53 -0
  10. data/lib/doorkeeper/config.rb +87 -62
  11. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  12. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  13. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  14. data/lib/doorkeeper/grant_flow.rb +45 -0
  15. data/lib/doorkeeper/helpers/controller.rb +4 -0
  16. data/lib/doorkeeper/models/access_grant_mixin.rb +1 -2
  17. data/lib/doorkeeper/models/access_token_mixin.rb +3 -3
  18. data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
  19. data/lib/doorkeeper/oauth/authorization/code.rb +4 -0
  20. data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
  21. data/lib/doorkeeper/oauth/authorization/token.rb +10 -4
  22. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +1 -1
  23. data/lib/doorkeeper/oauth/authorization_code_request.rb +10 -17
  24. data/lib/doorkeeper/oauth/base_request.rb +1 -1
  25. data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -1
  26. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +1 -0
  27. data/lib/doorkeeper/oauth/code_response.rb +17 -11
  28. data/lib/doorkeeper/oauth/error_response.rb +4 -3
  29. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -3
  30. data/lib/doorkeeper/oauth/password_access_token_request.rb +20 -1
  31. data/lib/doorkeeper/oauth/pre_authorization.rb +33 -8
  32. data/lib/doorkeeper/oauth/refresh_token_request.rb +13 -0
  33. data/lib/doorkeeper/orm/active_record/mixins/application.rb +6 -3
  34. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +5 -0
  35. data/lib/doorkeeper/orm/active_record.rb +4 -5
  36. data/lib/doorkeeper/rails/routes.rb +1 -3
  37. data/lib/doorkeeper/request.rb +49 -12
  38. data/lib/doorkeeper/version.rb +2 -6
  39. data/lib/doorkeeper.rb +5 -0
  40. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +1 -1
  41. data/lib/generators/doorkeeper/templates/initializer.rb +9 -7
  42. metadata +21 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 76b3a86e21584548c9b0c176512c844bee90ba9c447aaf09741abf54488093bb
4
- data.tar.gz: ce7a4ffdf3b0aebaa69f703b70f0109276205c9ec0b2f1e2c7b3e88cb4746f8b
3
+ metadata.gz: 71ef97409e242e0609d9c327836e2f90f92af440c8f989047b83435f7f8b052d
4
+ data.tar.gz: f12a030d12ca321fbf1b0acd4534707afba6c584b77d307698943a879cd33500
5
5
  SHA512:
6
- metadata.gz: 7192f9711713f15d323e85aa3ad4274b314a55dcc89ba945de52dca5dbbad2e267dc3252da353cd4991fae365a1161fd91d06c0bfcaba767163b4c54eafca125
7
- data.tar.gz: b5f324cfe8064b32254ca1c045bc24c54ab21a485bf3c6a9726bc995ab9dc24516872bf8ee314850b65f6ce3d879d0497e67416ea78c0f8f7566bdbfd48e024a
6
+ metadata.gz: bdda34cda76caffdeaec38be0c06ba733cc15480970bd78b48267c66764a64643423d61a2adb6c1c65643d3df2061ab3d86ad82baf970676276d7b1655fb846b
7
+ data.tar.gz: 8218ad9ad8248192f93253940623564784f339b78594cf00c000c33f9a6a9bd06f6cc5ee9fbcc207d4af3b499712387d39756c7ef6c709e9a7afe991efdfa5af
data/CHANGELOG.md CHANGED
@@ -7,7 +7,47 @@ User-visible changes worth mentioning.
7
7
 
8
8
  ## master
9
9
 
10
- - [#PR ID] Your PR description.
10
+ - [#PR ID] Add your PR description here.
11
+
12
+ ## 5.5.0.rc2
13
+
14
+ - [#1473] Enable `Applications` and `AuthorizedApplications` controllers in API mode.
15
+
16
+ **[IMPORTANT]** you can still skip these controllers using `skip_controllers` in
17
+ `use_doorkeeper` inside `routes.rb`. Please do it in case you don't need them.
18
+
19
+ - [#1472] Fix `establish_connection` configuration for custom defined models.
20
+ - [#1471] Add support for Ruby 3.0.
21
+ - [#1469] Check if `redirect_uri` exists.
22
+ - [#1465] Memoize nil doorkeeper_token.
23
+ - [#1459] Use built-in Ruby option to remove padding in PKCE code challenge value.
24
+ - [#1457] Make owner_id a bigint for newly-generated owner migrations
25
+ - [#1452] Empty previous_refresh_token only if present.
26
+ - [#1440] Validate empty host in redirect_uri.
27
+ - [#1438] Add form post response mode.
28
+ - [#1458] Make `config.skip_client_authentication_for_password_grant` a long term configuration option.
29
+
30
+ ## 5.5.0.rc1
31
+
32
+ - [#1435] Make error response not redirectable when client is unauthorized
33
+ - [#1426] Ensure ActiveRecord callbacks are executed on token revocation.
34
+ - [#1407] Remove redundant and complex to support helpers froms tests (`should_have_json`, etc).
35
+ - [#1416] Don't add introspection route if token introspection completely disabled.
36
+ - [#1410] Properly memoize `current_resource_owner` value (consider `nil` and `false` values).
37
+ - [#1415] Ignore PKCE params for non-PKCE grants.
38
+ - [#1418] Add ability to register custom OAuth Grant Flows.
39
+ - [#1420] Require client authentication for Resource Owner Password Grant as stated in OAuth RFC.
40
+
41
+ **[IMPORTANT]** you need to create a new OAuth client (`Doorkeeper::Application`) if you didn't
42
+ have it before and use client credentials in HTTP Basic auth if you previously used this grant
43
+ flow without client authentication. To opt out of this you could set the
44
+ `skip_client_authentication_for_password_grant` configuration option to `true`, but note that
45
+ this is in violation of the OAuth spec and represents a security risk.
46
+ All the users of your provider application now need to include client credentials when they use
47
+ this grant flow.
48
+
49
+ - [#1421] Add Resource Owner instance to authorization hook context for `custom_access_token_expires_in`
50
+ configuration option to allow resource owner based Access Tokens TTL.
11
51
 
12
52
  ## 5.4.0
13
53
 
@@ -17,7 +57,7 @@ User-visible changes worth mentioning.
17
57
 
18
58
  - [#1371] Add `#as_json` method and attributes serialization restriction for Application model.
19
59
  Fixes information disclosure vulnerability (CVE-2020-10187).
20
-
60
+
21
61
  **[IMPORTANT]** you need to re-implement `#as_json` method for Doorkeeper Application model
22
62
  if you previously used `#to_json` serialization with custom options or attributes or rely on
23
63
  JSON response from /oauth/applications.json or /oauth/authorized_applications.json. This change
@@ -31,17 +71,17 @@ User-visible changes worth mentioning.
31
71
  - [#1402] Handle trying authorization with client credentials.
32
72
 
33
73
  ## 5.4.0.rc1
34
- - [#1366] Sets expiry of token generated using `refresh_token` to that of original token. (Fixes #1364)
74
+ - [#1366] Sets expiry of token generated using `refresh_token` to that of original token. (Fixes #1364)
35
75
  - [#1354] Add `authorize_resource_owner_for_client` option to authorize the calling user to access an application.
36
76
  - [#1355] Allow to enable polymorphic Resource Owner association for Access Token & Grant
37
77
  models (`use_polymorphic_resource_owner` configuration option).
38
-
78
+
39
79
  **[IMPORTANT]** Review your custom patches or extensions for Doorkeeper internals if you
40
80
  have such - since now Doorkeeper passes Resource Owner instance to every objects and not
41
81
  just it's ID. See PR description for details.
42
-
82
+
43
83
  - [#1356] Remove duplicated scopes from Access Tokens and Grants on attribute assignment.
44
- - [#1357] Fix `Doorkeeper::OAuth::PreAuthorization#as_json` method causing
84
+ - [#1357] Fix `Doorkeeper::OAuth::PreAuthorization#as_json` method causing
45
85
  `Stack level too deep` error with AMS (fix #1312).
46
86
  - [#1358] Deprecate `active_record_options` configuration option.
47
87
  - [#1359] Refactor Doorkeeper configuration options DSL to make it easy to reuse it
@@ -53,7 +93,7 @@ User-visible changes worth mentioning.
53
93
  **[IMPORTANT]** now fully according to RFC 7009 nobody can do a revocation request without `client_id`
54
94
  (for public clients) and `client_secret` (for private clients). Please update your apps to include that
55
95
  info in the revocation request payload.
56
-
96
+
57
97
  - [#1373] Make Doorkeeper routes mapper reusable in extensions.
58
98
  - [#1374] Revoke and issue client credentials token in a transaction with a row lock.
59
99
  - [#1384] Add context object with auth/pre_auth and issued_token for authorization hooks.
@@ -98,9 +138,9 @@ User-visible changes worth mentioning.
98
138
 
99
139
  - [#1371] Backport: add `#as_json` method and attributes serialization restriction for Application model.
100
140
  Fixes information disclosure vulnerability (CVE-2020-10187).
101
-
141
+
102
142
  ## 5.2.4
103
-
143
+
104
144
  - [#1360] Backport: Increase `matching_token_for` batch lookup size to 10 000 and make it configurable.
105
145
 
106
146
  ## 5.2.3
@@ -52,10 +52,19 @@ module Doorkeeper
52
52
  def redirect_or_render(auth)
53
53
  if auth.redirectable?
54
54
  if Doorkeeper.configuration.api_only
55
- render(
56
- json: { status: :redirect, redirect_uri: auth.redirect_uri },
57
- status: auth.status,
58
- )
55
+ if pre_auth.form_post_response?
56
+ render(
57
+ json: { status: :post, redirect_uri: pre_auth.redirect_uri, body: auth.body },
58
+ status: auth.status,
59
+ )
60
+ else
61
+ render(
62
+ json: { status: :redirect, redirect_uri: auth.redirect_uri },
63
+ status: auth.status,
64
+ )
65
+ end
66
+ elsif pre_auth.form_post_response?
67
+ render :form_post
59
68
  else
60
69
  redirect_to auth.redirect_uri
61
70
  end
@@ -82,8 +91,10 @@ module Doorkeeper
82
91
  code_challenge
83
92
  code_challenge_method
84
93
  response_type
94
+ response_mode
85
95
  redirect_uri
86
- scope state
96
+ scope
97
+ state
87
98
  ]
88
99
  end
89
100
 
@@ -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,
@@ -12,32 +14,6 @@ module Doorkeeper
12
14
 
13
15
  # OAuth 2.0 Token Revocation - http://tools.ietf.org/html/rfc7009
14
16
  def revoke
15
- # @see 2.1. Revocation Request
16
- #
17
- # The client constructs the request by including the following
18
- # parameters using the "application/x-www-form-urlencoded" format in
19
- # the HTTP request entity-body:
20
- # token REQUIRED.
21
- # token_type_hint OPTIONAL.
22
- #
23
- # The client also includes its authentication credentials as described
24
- # in Section 2.3. of [RFC6749].
25
- #
26
- # The authorization server first validates the client credentials (in
27
- # case of a confidential client) and then verifies whether the token
28
- # was issued to the client making the revocation request.
29
- unless server.client
30
- # If this validation [client credentials / token ownership] fails, the request is
31
- # refused and the client is informed of the error by the authorization server as
32
- # described below.
33
- #
34
- # @see 2.2.1. Error Response
35
- #
36
- # The error presentation conforms to the definition in Section 5.2 of [RFC6749].
37
- render json: revocation_error_response, status: :forbidden
38
- return
39
- end
40
-
41
17
  # The authorization server responds with HTTP status code 200 if the client
42
18
  # submitted an invalid token or the token has been revoked successfully.
43
19
  if token.blank?
@@ -68,7 +44,39 @@ module Doorkeeper
68
44
 
69
45
  private
70
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
+
71
76
  # OAuth 2.0 Section 2.1 defines two client types, "public" & "confidential".
77
+ #
78
+ # RFC7009
79
+ # Section 5. Security Considerations
72
80
  # A malicious client may attempt to guess valid tokens on this endpoint
73
81
  # by making revocation requests against potential token strings.
74
82
  # According to this specification, a client's request must contain a
@@ -35,18 +35,22 @@
35
35
 
36
36
  <h4><%= t('.callback_urls') %>:</h4>
37
37
 
38
- <table>
39
- <% @application.redirect_uri.split.each do |uri| %>
40
- <tr>
41
- <td>
42
- <code class="bg-light"><%= uri %></code>
43
- </td>
44
- <td>
45
- <%= 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' %>
46
- </td>
47
- </tr>
48
- <% end %>
49
- </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 %>
50
54
  </div>
51
55
 
52
56
  <div class="col-md-4">
@@ -0,0 +1,11 @@
1
+ <header class="page-header">
2
+ <h1><%= t('.title') %></h1>
3
+ </header>
4
+
5
+ <main role="main" onload="document.forms[0].submit()">
6
+ <%= form_tag @pre_auth.redirect_uri, method: :post do %>
7
+ <% @authorize_response.body.each do |key, value| %>
8
+ <%= hidden_field_tag key, value %>
9
+ <% end %>
10
+ <% end %>
11
+ </main>
@@ -72,6 +72,8 @@ en:
72
72
  able_to: 'This application will be able to'
73
73
  show:
74
74
  title: 'Authorization code'
75
+ form_post:
76
+ title: 'Submit this form'
75
77
 
76
78
  authorized_applications:
77
79
  confirmations:
@@ -93,7 +95,6 @@ en:
93
95
  invalid_request:
94
96
  unknown: 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
95
97
  missing_param: 'Missing required parameter: %{value}.'
96
- not_support_pkce: 'Invalid code_verifier parameter. Server does not support pkce.'
97
98
  request_not_authorized: 'Request need to be authorized. Required parameter for authorizing request is missing or invalid.'
98
99
  invalid_redirect_uri: "The requested redirect uri is malformed or doesn't match client redirect URI."
99
100
  unauthorized_client: 'The client is not authorized to perform this request using this method.'
@@ -110,6 +111,7 @@ en:
110
111
 
111
112
  # Access grant errors
112
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.'
113
115
 
114
116
  # Access token errors
115
117
  invalid_client: 'Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method.'
@@ -45,9 +45,7 @@ module Doorkeeper
45
45
  define_method name do |*args, &block|
46
46
  if (deprecation_opts = options[:deprecated])
47
47
  warning = "[DOORKEEPER] #{name} has been deprecated and will soon be removed"
48
- if deprecation_opts.is_a?(Hash)
49
- warning = "#{warning}\n#{deprecation_opts.fetch(:message)}"
50
- end
48
+ warning = "#{warning}\n#{deprecation_opts.fetch(:message)}" if deprecation_opts.is_a?(Hash)
51
49
 
52
50
  Kernel.warn(warning)
53
51
  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
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "doorkeeper/config/option"
4
3
  require "doorkeeper/config/abstract_builder"
4
+ require "doorkeeper/config/option"
5
+ require "doorkeeper/config/validations"
5
6
 
6
7
  module Doorkeeper
7
8
  # Defines a MissingConfiguration error for a missing Doorkeeper configuration
@@ -28,6 +29,8 @@ module Doorkeeper
28
29
  @config
29
30
  end
30
31
 
32
+ # @return [Doorkeeper::Config] configuration instance
33
+ #
31
34
  def configuration
32
35
  @config || (raise MissingConfiguration)
33
36
  end
@@ -219,6 +222,7 @@ module Doorkeeper
219
222
  mattr_reader(:builder_class) { Builder }
220
223
 
221
224
  extend Option
225
+ include Validations
222
226
 
223
227
  option :resource_owner_authenticator,
224
228
  as: :authenticate_resource_owner,
@@ -267,7 +271,6 @@ module Doorkeeper
267
271
  option :grant_flows, default: %w[authorization_code client_credentials]
268
272
  option :handle_auth_errors, default: :render
269
273
  option :token_lookup_batch_size, default: 10_000
270
-
271
274
  # Sets the token_reuse_limit
272
275
  # It will be used only when reuse_access_token option in enabled
273
276
  # By default it will be 100
@@ -275,6 +278,17 @@ module Doorkeeper
275
278
  # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/1189
276
279
  option :token_reuse_limit, default: 100
277
280
 
281
+ # This is discouraged. Spec says that password grants always require a client.
282
+ #
283
+ # See https://github.com/doorkeeper-gem/doorkeeper/issues/1412#issuecomment-632750422
284
+ # and https://github.com/doorkeeper-gem/doorkeeper/pull/1420
285
+ #
286
+ # Since many applications use this unsafe behavior in the wild, this is kept as a
287
+ # not-recommended option. You should be aware that you are not following the OAuth
288
+ # spec, and understand the security implications of doing so.
289
+ option :skip_client_authentication_for_password_grant,
290
+ default: false
291
+
278
292
  option :active_record_options,
279
293
  default: {},
280
294
  deprecated: { message: "Customize Doorkeeper models instead" }
@@ -423,13 +437,6 @@ module Doorkeeper
423
437
  :token_secret_fallback_strategy,
424
438
  :application_secret_fallback_strategy
425
439
 
426
- # Return the valid subset of this configuration
427
- def validate!
428
- validate_reuse_access_token_value
429
- validate_token_reuse_limit
430
- validate_secret_strategies
431
- end
432
-
433
440
  # Doorkeeper Access Token model class.
434
441
  #
435
442
  # @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
@@ -545,12 +552,77 @@ module Doorkeeper
545
552
  ]
546
553
  end
547
554
 
555
+ def enabled_grant_flows
556
+ @enabled_grant_flows ||= calculate_grant_flows.map { |name| Doorkeeper::GrantFlow.get(name) }.compact
557
+ end
558
+
559
+ def authorization_response_flows
560
+ @authorization_response_flows ||= enabled_grant_flows.select(&:handles_response_type?) +
561
+ deprecated_authorization_flows
562
+ end
563
+
564
+ def token_grant_flows
565
+ @token_grant_flows ||= calculate_token_grant_flows
566
+ end
567
+
548
568
  def authorization_response_types
549
- @authorization_response_types ||= calculate_authorization_response_types.freeze
569
+ authorization_response_flows.map(&:response_type_matches)
550
570
  end
551
571
 
552
572
  def token_grant_types
553
- @token_grant_types ||= calculate_token_grant_types.freeze
573
+ token_grant_flows.map(&:grant_type_matches)
574
+ end
575
+
576
+ # [NOTE]: deprecated and will be removed soon
577
+ def deprecated_token_grant_types_resolver
578
+ @deprecated_token_grant_types ||= calculate_token_grant_types
579
+ end
580
+
581
+ # [NOTE]: deprecated and will be removed soon
582
+ def deprecated_authorization_flows
583
+ response_types = calculate_authorization_response_types
584
+
585
+ if response_types.any?
586
+ ::Kernel.warn <<~WARNING
587
+ Please, don't patch Doorkeeper::Config#calculate_authorization_response_types method.
588
+ Register your custom grant flows using the public API:
589
+ `Doorkeeper::GrantFlow.register(grant_flow_name, **options)`.
590
+ WARNING
591
+ end
592
+
593
+ response_types.map do |response_type|
594
+ Doorkeeper::GrantFlow::FallbackFlow.new(response_type, response_type_matches: response_type)
595
+ end
596
+ end
597
+
598
+ # [NOTE]: deprecated and will be removed soon
599
+ def calculate_authorization_response_types
600
+ []
601
+ end
602
+
603
+ # [NOTE]: deprecated and will be removed soon
604
+ def calculate_token_grant_types
605
+ types = grant_flows - ["implicit"]
606
+ types << "refresh_token" if refresh_token_enabled?
607
+ types
608
+ end
609
+
610
+ # Calculates grant flows configured by the user in Doorkeeper
611
+ # configuration considering registered aliases that is exposed
612
+ # to single or multiple other flows.
613
+ #
614
+ def calculate_grant_flows
615
+ configured_flows = grant_flows.map(&:to_s)
616
+ aliases = Doorkeeper::GrantFlow.aliases.keys.map(&:to_s)
617
+
618
+ flows = configured_flows - aliases
619
+ aliases.each do |flow_alias|
620
+ next unless configured_flows.include?(flow_alias)
621
+
622
+ flows.concat(Doorkeeper::GrantFlow.expand_alias(flow_alias))
623
+ end
624
+
625
+ flows.flatten.uniq
554
626
  end
555
627
 
556
628
  def allow_blank_redirect_uri?(application = nil)
@@ -579,57 +651,10 @@ module Doorkeeper
579
651
  !!(defined?(var) && var)
580
652
  end
581
653
 
582
- # Determines what values are acceptable for 'response_type' param in
583
- # authorization request endpoint, and return them as an array of strings.
584
- #
585
- def calculate_authorization_response_types
586
- types = []
587
- types << "code" if grant_flows.include? "authorization_code"
588
- types << "token" if grant_flows.include? "implicit"
589
- types
590
- end
591
-
592
- # Determines what values are acceptable for 'grant_type' param token
593
- # request endpoint, and return them in array.
594
- #
595
- def calculate_token_grant_types
596
- types = grant_flows - ["implicit"]
597
- types << "refresh_token" if refresh_token_enabled?
598
- types
599
- end
600
-
601
- # Determine whether +reuse_access_token+ and a non-restorable
602
- # +token_secret_strategy+ have both been activated.
603
- #
604
- # In that case, disable reuse_access_token value and warn the user.
605
- def validate_reuse_access_token_value
606
- strategy = token_secret_strategy
607
- return if !reuse_access_token || strategy.allows_restoring_secrets?
608
-
609
- ::Rails.logger.warn(
610
- "You have configured both reuse_access_token " \
611
- "AND strategy strategy '#{strategy}' that cannot restore tokens. " \
612
- "This combination is unsupported. reuse_access_token will be disabled",
613
- )
614
- @reuse_access_token = false
615
- end
616
-
617
- # Validate that the provided strategies are valid for
618
- # tokens and applications
619
- def validate_secret_strategies
620
- token_secret_strategy.validate_for :token
621
- application_secret_strategy.validate_for :application
622
- end
623
-
624
- def validate_token_reuse_limit
625
- return if !reuse_access_token ||
626
- (token_reuse_limit > 0 && token_reuse_limit <= 100)
627
-
628
- ::Rails.logger.warn(
629
- "You have configured an invalid value for token_reuse_limit option. " \
630
- "It will be set to default 100",
631
- )
632
- @token_reuse_limit = 100
654
+ def calculate_token_grant_flows
655
+ flows = enabled_grant_flows.select(&:handles_grant_type?)
656
+ flows << Doorkeeper::GrantFlow.get("refresh_token") if refresh_token_enabled?
657
+ flows
633
658
  end
634
659
  end
635
660
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module GrantFlow
5
+ class FallbackFlow < Flow
6
+ def handles_grant_type?
7
+ false
8
+ end
9
+
10
+ def handles_response_type?
11
+ false
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module GrantFlow
5
+ class Flow
6
+ attr_reader :name, :grant_type_matches, :grant_type_strategy,
7
+ :response_type_matches, :response_type_strategy,
8
+ :response_mode_matches
9
+
10
+ def initialize(name, **options)
11
+ @name = name
12
+ @grant_type_matches = options[:grant_type_matches]
13
+ @grant_type_strategy = options[:grant_type_strategy]
14
+ @response_type_matches = options[:response_type_matches]
15
+ @response_type_strategy = options[:response_type_strategy]
16
+ @response_mode_matches = options[:response_mode_matches]
17
+ end
18
+
19
+ def handles_grant_type?
20
+ grant_type_matches.present?
21
+ end
22
+
23
+ def handles_response_type?
24
+ response_type_matches.present?
25
+ end
26
+
27
+ def matches_grant_type?(value)
28
+ grant_type_matches === value
29
+ end
30
+
31
+ def matches_response_type?(value)
32
+ response_type_matches === value
33
+ end
34
+
35
+ def default_response_mode
36
+ response_mode_matches[0]
37
+ end
38
+
39
+ def matches_response_mode?(value)
40
+ response_mode_matches.include?(value)
41
+ end
42
+ end
43
+ end
44
+ end