doorkeeper 3.1.0 → 5.6.2

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 (270) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1079 -0
  3. data/README.md +114 -326
  4. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  5. data/app/controllers/doorkeeper/application_controller.rb +7 -6
  6. data/app/controllers/doorkeeper/application_metal_controller.rb +9 -12
  7. data/app/controllers/doorkeeper/applications_controller.rb +66 -21
  8. data/app/controllers/doorkeeper/authorizations_controller.rb +100 -18
  9. data/app/controllers/doorkeeper/authorized_applications_controller.rb +23 -4
  10. data/app/controllers/doorkeeper/token_info_controller.rb +16 -4
  11. data/app/controllers/doorkeeper/tokens_controller.rb +138 -22
  12. data/app/helpers/doorkeeper/dashboard_helper.rb +15 -9
  13. data/app/views/doorkeeper/applications/_delete_form.html.erb +4 -3
  14. data/app/views/doorkeeper/applications/_form.html.erb +33 -21
  15. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  16. data/app/views/doorkeeper/applications/index.html.erb +18 -6
  17. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  18. data/app/views/doorkeeper/applications/show.html.erb +40 -16
  19. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  20. data/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
  21. data/app/views/doorkeeper/authorizations/new.html.erb +17 -11
  22. data/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +1 -2
  23. data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
  24. data/app/views/layouts/doorkeeper/admin.html.erb +16 -14
  25. data/config/locales/en.yml +37 -9
  26. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  27. data/lib/doorkeeper/config/option.rb +82 -0
  28. data/lib/doorkeeper/config/validations.rb +53 -0
  29. data/lib/doorkeeper/config.rb +602 -142
  30. data/lib/doorkeeper/engine.rb +22 -7
  31. data/lib/doorkeeper/errors.rb +37 -10
  32. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  33. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  34. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  35. data/lib/doorkeeper/grant_flow.rb +45 -0
  36. data/lib/doorkeeper/grape/authorization_decorator.rb +6 -4
  37. data/lib/doorkeeper/grape/helpers.rb +24 -12
  38. data/lib/doorkeeper/helpers/controller.rb +49 -27
  39. data/lib/doorkeeper/models/access_grant_mixin.rb +99 -16
  40. data/lib/doorkeeper/models/access_token_mixin.rb +386 -77
  41. data/lib/doorkeeper/models/application_mixin.rb +73 -30
  42. data/lib/doorkeeper/models/concerns/accessible.rb +6 -0
  43. data/lib/doorkeeper/models/concerns/expirable.rb +20 -6
  44. data/lib/doorkeeper/models/concerns/expiration_time_sql_math.rb +88 -0
  45. data/lib/doorkeeper/models/concerns/orderable.rb +15 -0
  46. data/lib/doorkeeper/models/concerns/ownership.rb +4 -2
  47. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  48. data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
  49. data/lib/doorkeeper/models/concerns/revocable.rb +13 -2
  50. data/lib/doorkeeper/models/concerns/scopes.rb +12 -2
  51. data/lib/doorkeeper/models/concerns/secret_storable.rb +106 -0
  52. data/lib/doorkeeper/oauth/authorization/code.rb +48 -12
  53. data/lib/doorkeeper/oauth/authorization/context.rb +17 -0
  54. data/lib/doorkeeper/oauth/authorization/token.rb +72 -28
  55. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +22 -18
  56. data/lib/doorkeeper/oauth/authorization_code_request.rb +64 -14
  57. data/lib/doorkeeper/oauth/base_request.rb +66 -0
  58. data/lib/doorkeeper/oauth/base_response.rb +31 -0
  59. data/lib/doorkeeper/oauth/client/credentials.rb +23 -10
  60. data/lib/doorkeeper/oauth/client.rb +10 -12
  61. data/lib/doorkeeper/oauth/client_credentials/creator.rb +48 -4
  62. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +17 -9
  63. data/lib/doorkeeper/oauth/client_credentials/validator.rb +55 -0
  64. data/lib/doorkeeper/oauth/client_credentials_request.rb +14 -15
  65. data/lib/doorkeeper/oauth/code_request.rb +8 -12
  66. data/lib/doorkeeper/oauth/code_response.rb +31 -19
  67. data/lib/doorkeeper/oauth/error.rb +5 -3
  68. data/lib/doorkeeper/oauth/error_response.rb +41 -20
  69. data/lib/doorkeeper/oauth/forbidden_token_response.rb +11 -3
  70. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +24 -19
  71. data/lib/doorkeeper/oauth/helpers/unique_token.rb +20 -3
  72. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +55 -4
  73. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  74. data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
  75. data/lib/doorkeeper/oauth/invalid_token_response.rb +31 -5
  76. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  77. data/lib/doorkeeper/oauth/password_access_token_request.rb +46 -18
  78. data/lib/doorkeeper/oauth/pre_authorization.rb +135 -26
  79. data/lib/doorkeeper/oauth/refresh_token_request.rb +67 -30
  80. data/lib/doorkeeper/oauth/scopes.rb +26 -12
  81. data/lib/doorkeeper/oauth/token.rb +28 -25
  82. data/lib/doorkeeper/oauth/token_introspection.rb +202 -0
  83. data/lib/doorkeeper/oauth/token_request.rb +8 -21
  84. data/lib/doorkeeper/oauth/token_response.rb +14 -10
  85. data/lib/doorkeeper/oauth.rb +13 -0
  86. data/lib/doorkeeper/orm/active_record/access_grant.rb +6 -4
  87. data/lib/doorkeeper/orm/active_record/access_token.rb +5 -17
  88. data/lib/doorkeeper/orm/active_record/application.rb +6 -20
  89. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +69 -0
  90. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +81 -0
  91. data/lib/doorkeeper/orm/active_record/mixins/application.rb +214 -0
  92. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
  93. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +33 -0
  94. data/lib/doorkeeper/orm/active_record.rb +36 -26
  95. data/lib/doorkeeper/rails/helpers.rb +14 -15
  96. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  97. data/lib/doorkeeper/rails/routes/mapper.rb +4 -2
  98. data/lib/doorkeeper/rails/routes/mapping.rb +10 -8
  99. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  100. data/lib/doorkeeper/rails/routes.rb +45 -28
  101. data/lib/doorkeeper/rake/db.rake +40 -0
  102. data/lib/doorkeeper/rake/setup.rake +6 -0
  103. data/lib/doorkeeper/rake.rb +14 -0
  104. data/lib/doorkeeper/request/authorization_code.rb +12 -4
  105. data/lib/doorkeeper/request/client_credentials.rb +3 -3
  106. data/lib/doorkeeper/request/code.rb +1 -1
  107. data/lib/doorkeeper/request/password.rb +5 -4
  108. data/lib/doorkeeper/request/refresh_token.rb +6 -5
  109. data/lib/doorkeeper/request/strategy.rb +4 -2
  110. data/lib/doorkeeper/request/token.rb +1 -1
  111. data/lib/doorkeeper/request.rb +62 -29
  112. data/lib/doorkeeper/secret_storing/base.rb +64 -0
  113. data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
  114. data/lib/doorkeeper/secret_storing/plain.rb +33 -0
  115. data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
  116. data/lib/doorkeeper/server.rb +9 -19
  117. data/lib/doorkeeper/stale_records_cleaner.rb +24 -0
  118. data/lib/doorkeeper/validations.rb +5 -2
  119. data/lib/doorkeeper/version.rb +12 -1
  120. data/lib/doorkeeper.rb +112 -56
  121. data/lib/generators/doorkeeper/application_owner_generator.rb +28 -13
  122. data/lib/generators/doorkeeper/confidential_applications_generator.rb +33 -0
  123. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  124. data/lib/generators/doorkeeper/install_generator.rb +19 -9
  125. data/lib/generators/doorkeeper/migration_generator.rb +27 -10
  126. data/lib/generators/doorkeeper/pkce_generator.rb +33 -0
  127. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +41 -0
  128. data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  129. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +9 -0
  130. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +13 -0
  131. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +8 -0
  132. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  133. data/lib/generators/doorkeeper/templates/initializer.rb +417 -32
  134. data/lib/generators/doorkeeper/templates/migration.rb.erb +88 -0
  135. data/lib/generators/doorkeeper/views_generator.rb +8 -4
  136. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  137. metadata +163 -280
  138. data/.gitignore +0 -14
  139. data/.hound.yml +0 -13
  140. data/.rspec +0 -1
  141. data/.travis.yml +0 -22
  142. data/CONTRIBUTING.md +0 -45
  143. data/Gemfile +0 -10
  144. data/NEWS.md +0 -525
  145. data/RELEASING.md +0 -17
  146. data/Rakefile +0 -20
  147. data/app/validators/redirect_uri_validator.rb +0 -34
  148. data/doorkeeper.gemspec +0 -27
  149. data/lib/doorkeeper/oauth/client/methods.rb +0 -18
  150. data/lib/doorkeeper/oauth/client_credentials/validation.rb +0 -45
  151. data/lib/doorkeeper/oauth/request_concern.rb +0 -48
  152. data/lib/generators/doorkeeper/application_scopes_generator.rb +0 -34
  153. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb +0 -7
  154. data/lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb +0 -5
  155. data/lib/generators/doorkeeper/templates/migration.rb +0 -50
  156. data/spec/controllers/applications_controller_spec.rb +0 -58
  157. data/spec/controllers/authorizations_controller_spec.rb +0 -203
  158. data/spec/controllers/protected_resources_controller_spec.rb +0 -271
  159. data/spec/controllers/token_info_controller_spec.rb +0 -52
  160. data/spec/controllers/tokens_controller_spec.rb +0 -88
  161. data/spec/dummy/Rakefile +0 -7
  162. data/spec/dummy/app/controllers/application_controller.rb +0 -3
  163. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -7
  164. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -12
  165. data/spec/dummy/app/controllers/home_controller.rb +0 -17
  166. data/spec/dummy/app/controllers/metal_controller.rb +0 -11
  167. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -11
  168. data/spec/dummy/app/helpers/application_helper.rb +0 -5
  169. data/spec/dummy/app/models/user.rb +0 -9
  170. data/spec/dummy/app/views/home/index.html.erb +0 -0
  171. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  172. data/spec/dummy/config/application.rb +0 -57
  173. data/spec/dummy/config/boot.rb +0 -9
  174. data/spec/dummy/config/database.yml +0 -15
  175. data/spec/dummy/config/environment.rb +0 -5
  176. data/spec/dummy/config/environments/development.rb +0 -29
  177. data/spec/dummy/config/environments/production.rb +0 -62
  178. data/spec/dummy/config/environments/test.rb +0 -55
  179. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
  180. data/spec/dummy/config/initializers/doorkeeper.rb +0 -96
  181. data/spec/dummy/config/initializers/secret_token.rb +0 -9
  182. data/spec/dummy/config/initializers/session_store.rb +0 -8
  183. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
  184. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  185. data/spec/dummy/config/routes.rb +0 -52
  186. data/spec/dummy/config.ru +0 -4
  187. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -9
  188. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -5
  189. data/spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb +0 -41
  190. data/spec/dummy/db/migrate/20130902175349_add_owner_to_application.rb +0 -7
  191. data/spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb +0 -5
  192. data/spec/dummy/db/schema.rb +0 -66
  193. data/spec/dummy/public/404.html +0 -26
  194. data/spec/dummy/public/422.html +0 -26
  195. data/spec/dummy/public/500.html +0 -26
  196. data/spec/dummy/public/favicon.ico +0 -0
  197. data/spec/dummy/script/rails +0 -6
  198. data/spec/factories.rb +0 -26
  199. data/spec/generators/application_owner_generator_spec.rb +0 -22
  200. data/spec/generators/install_generator_spec.rb +0 -31
  201. data/spec/generators/migration_generator_spec.rb +0 -20
  202. data/spec/generators/templates/routes.rb +0 -3
  203. data/spec/generators/views_generator_spec.rb +0 -27
  204. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -24
  205. data/spec/lib/config_spec.rb +0 -317
  206. data/spec/lib/doorkeeper_spec.rb +0 -28
  207. data/spec/lib/models/expirable_spec.rb +0 -51
  208. data/spec/lib/models/revocable_spec.rb +0 -36
  209. data/spec/lib/models/scopes_spec.rb +0 -43
  210. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -42
  211. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -80
  212. data/spec/lib/oauth/client/credentials_spec.rb +0 -47
  213. data/spec/lib/oauth/client/methods_spec.rb +0 -54
  214. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -44
  215. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -86
  216. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -54
  217. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
  218. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -104
  219. data/spec/lib/oauth/client_spec.rb +0 -39
  220. data/spec/lib/oauth/code_request_spec.rb +0 -45
  221. data/spec/lib/oauth/error_response_spec.rb +0 -61
  222. data/spec/lib/oauth/error_spec.rb +0 -23
  223. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -23
  224. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -64
  225. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -20
  226. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -104
  227. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -28
  228. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -90
  229. data/spec/lib/oauth/pre_authorization_spec.rb +0 -155
  230. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -123
  231. data/spec/lib/oauth/scopes_spec.rb +0 -123
  232. data/spec/lib/oauth/token_request_spec.rb +0 -98
  233. data/spec/lib/oauth/token_response_spec.rb +0 -85
  234. data/spec/lib/oauth/token_spec.rb +0 -109
  235. data/spec/lib/request/strategy_spec.rb +0 -53
  236. data/spec/lib/server_spec.rb +0 -52
  237. data/spec/models/doorkeeper/access_grant_spec.rb +0 -36
  238. data/spec/models/doorkeeper/access_token_spec.rb +0 -350
  239. data/spec/models/doorkeeper/application_spec.rb +0 -187
  240. data/spec/requests/applications/applications_request_spec.rb +0 -94
  241. data/spec/requests/applications/authorized_applications_spec.rb +0 -30
  242. data/spec/requests/endpoints/authorization_spec.rb +0 -72
  243. data/spec/requests/endpoints/token_spec.rb +0 -64
  244. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -66
  245. data/spec/requests/flows/authorization_code_spec.rb +0 -156
  246. data/spec/requests/flows/client_credentials_spec.rb +0 -58
  247. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -32
  248. data/spec/requests/flows/implicit_grant_spec.rb +0 -61
  249. data/spec/requests/flows/password_spec.rb +0 -94
  250. data/spec/requests/flows/refresh_token_spec.rb +0 -104
  251. data/spec/requests/flows/revoke_token_spec.rb +0 -143
  252. data/spec/requests/flows/skip_authorization_spec.rb +0 -59
  253. data/spec/requests/protected_resources/metal_spec.rb +0 -14
  254. data/spec/requests/protected_resources/private_api_spec.rb +0 -81
  255. data/spec/routing/custom_controller_routes_spec.rb +0 -71
  256. data/spec/routing/default_routes_spec.rb +0 -35
  257. data/spec/routing/scoped_routes_spec.rb +0 -31
  258. data/spec/spec_helper.rb +0 -2
  259. data/spec/spec_helper_integration.rb +0 -56
  260. data/spec/support/dependencies/factory_girl.rb +0 -2
  261. data/spec/support/helpers/access_token_request_helper.rb +0 -11
  262. data/spec/support/helpers/authorization_request_helper.rb +0 -41
  263. data/spec/support/helpers/config_helper.rb +0 -9
  264. data/spec/support/helpers/model_helper.rb +0 -45
  265. data/spec/support/helpers/request_spec_helper.rb +0 -76
  266. data/spec/support/helpers/url_helper.rb +0 -55
  267. data/spec/support/orm/active_record.rb +0 -3
  268. data/spec/support/shared/controllers_shared_context.rb +0 -60
  269. data/spec/support/shared/models_shared_examples.rb +0 -52
  270. data/spec/validators/redirect_uri_validator_spec.rb +0 -78
@@ -1,207 +1,582 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "doorkeeper/config/abstract_builder"
4
+ require "doorkeeper/config/option"
5
+ require "doorkeeper/config/validations"
6
+
1
7
  module Doorkeeper
8
+ # Defines a MissingConfiguration error for a missing Doorkeeper configuration
9
+ #
2
10
  class MissingConfiguration < StandardError
3
11
  def initialize
4
- super('Configuration for doorkeeper missing. Do you have doorkeeper initializer?')
12
+ super("Configuration for doorkeeper missing. Do you have doorkeeper initializer?")
5
13
  end
6
14
  end
7
15
 
8
- def self.configure(&block)
9
- @config = Config::Builder.new(&block).build
10
- setup_orm_adapter
11
- setup_orm_models
12
- setup_application_owner if @config.enable_application_owner?
13
- check_requirements
14
- end
15
-
16
- def self.configuration
17
- @config || (fail MissingConfiguration.new)
18
- end
16
+ # Doorkeeper option DSL could be reused in extensions to build their own
17
+ # configurations. To use the Option DSL gems need to define `builder_class` method
18
+ # that returns configuration Builder class. This exception raises when they don't
19
+ # define it.
20
+ #
21
+ class MissingConfigurationBuilderClass < StandardError; end
19
22
 
20
- def self.check_requirements
21
- @orm_adapter.check_requirements!(configuration)
22
- end
23
+ class << self
24
+ attr_reader :orm_adapter
23
25
 
24
- def self.setup_orm_adapter
25
- @orm_adapter = "doorkeeper/orm/#{configuration.orm}".classify.constantize
26
- rescue NameError => e
27
- fail e, "ORM adapter not found (#{configuration.orm})", <<-ERROR_MSG.squish
28
- [doorkeeper] ORM adapter not found (#{configuration.orm}), or there was an error
29
- trying to load it.
26
+ def configure(&block)
27
+ @config = Config::Builder.new(&block).build
28
+ end
30
29
 
31
- You probably need to add the related gem for this adapter to work with
32
- doorkeeper.
33
- ERROR_MSG
34
- end
30
+ # @return [Doorkeeper::Config] configuration instance
31
+ #
32
+ def configuration
33
+ @config || (raise MissingConfiguration)
34
+ end
35
35
 
36
- def self.setup_orm_models
37
- @orm_adapter.initialize_models!
38
- end
36
+ alias config configuration
39
37
 
40
- def self.setup_application_owner
41
- @orm_adapter.initialize_application_owner!
42
- end
38
+ def setup
39
+ setup_orm_adapter
40
+ run_orm_hooks
41
+ config.clear_cache!
43
42
 
44
- class Config
45
- class Builder
46
- def initialize(&block)
47
- @config = Config.new
48
- instance_eval(&block)
43
+ # Deprecated, will be removed soon
44
+ unless configuration.orm == :active_record
45
+ setup_orm_models
46
+ setup_application_owner
49
47
  end
48
+ end
49
+
50
+ def setup_orm_adapter
51
+ @orm_adapter = "doorkeeper/orm/#{configuration.orm}".classify.constantize
52
+ rescue NameError => e
53
+ raise e, "ORM adapter not found (#{configuration.orm})", <<-ERROR_MSG.strip_heredoc
54
+ [DOORKEEPER] ORM adapter not found (#{configuration.orm}), or there was an error
55
+ trying to load it.
56
+
57
+ You probably need to add the related gem for this adapter to work with
58
+ doorkeeper.
59
+ ERROR_MSG
60
+ end
50
61
 
51
- def build
52
- @config
62
+ def run_orm_hooks
63
+ if @orm_adapter.respond_to?(:run_hooks)
64
+ @orm_adapter.run_hooks
65
+ else
66
+ ::Kernel.warn <<~MSG.strip_heredoc
67
+ [DOORKEEPER] ORM "#{configuration.orm}" should move all it's setup logic under `#run_hooks` method for
68
+ the #{@orm_adapter.name}. Later versions of Doorkeeper will no longer support `setup_orm_models` and
69
+ `setup_application_owner` API.
70
+ MSG
53
71
  end
72
+ end
73
+
74
+ def setup_orm_models
75
+ @orm_adapter.initialize_models!
76
+ end
77
+
78
+ def setup_application_owner
79
+ @orm_adapter.initialize_application_owner!
80
+ end
81
+ end
54
82
 
83
+ class Config
84
+ # Default Doorkeeper configuration builder
85
+ class Builder < AbstractBuilder
86
+ # Provide support for an owner to be assigned to each registered
87
+ # application (disabled by default)
88
+ # Optional parameter confirmation: true (default false) if you want
89
+ # to enforce ownership of a registered application
90
+ #
91
+ # @param opts [Hash] the options to confirm if an application owner
92
+ # is present
93
+ # @option opts[Boolean] :confirmation (false)
94
+ # Set confirm_application_owner variable
55
95
  def enable_application_owner(opts = {})
56
- @config.instance_variable_set('@enable_application_owner', true)
96
+ @config.instance_variable_set(:@enable_application_owner, true)
57
97
  confirm_application_owner if opts[:confirmation].present? && opts[:confirmation]
58
98
  end
59
99
 
60
100
  def confirm_application_owner
61
- @config.instance_variable_set('@confirm_application_owner', true)
101
+ @config.instance_variable_set(:@confirm_application_owner, true)
62
102
  end
63
103
 
104
+ # Define default access token scopes for your provider
105
+ #
106
+ # @param scopes [Array] Default set of access (OAuth::Scopes.new)
107
+ # token scopes
64
108
  def default_scopes(*scopes)
65
- @config.instance_variable_set('@default_scopes', OAuth::Scopes.from_array(scopes))
109
+ @config.instance_variable_set(:@default_scopes, OAuth::Scopes.from_array(scopes))
66
110
  end
67
111
 
112
+ # Define default access token scopes for your provider
113
+ #
114
+ # @param scopes [Array] Optional set of access (OAuth::Scopes.new)
115
+ # token scopes
68
116
  def optional_scopes(*scopes)
69
- @config.instance_variable_set('@optional_scopes', OAuth::Scopes.from_array(scopes))
117
+ @config.instance_variable_set(:@optional_scopes, OAuth::Scopes.from_array(scopes))
118
+ end
119
+
120
+ # Define scopes_by_grant_type to limit certain scope to certain grant_type
121
+ # @param { Hash } with grant_types as keys.
122
+ # Default set to {} i.e. no limitation on scopes usage
123
+ def scopes_by_grant_type(hash = {})
124
+ @config.instance_variable_set(:@scopes_by_grant_type, hash)
70
125
  end
71
126
 
127
+ # Change the way client credentials are retrieved from the request object.
128
+ # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
129
+ # falls back to the `:client_id` and `:client_secret` params from the
130
+ # `params` object.
131
+ #
132
+ # @param methods [Array] Define client credentials
72
133
  def client_credentials(*methods)
73
- @config.instance_variable_set('@client_credentials', methods)
134
+ @config.instance_variable_set(:@client_credentials_methods, methods)
74
135
  end
75
136
 
137
+ # Change the way access token is authenticated from the request object.
138
+ # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
139
+ # falls back to the `:access_token` or `:bearer_token` params from the
140
+ # `params` object.
141
+ #
142
+ # @param methods [Array] Define access token methods
76
143
  def access_token_methods(*methods)
77
- @config.instance_variable_set('@access_token_methods', methods)
144
+ @config.instance_variable_set(:@access_token_methods, methods)
145
+ end
146
+
147
+ # Issue access tokens with refresh token (disabled if not set)
148
+ def use_refresh_token(enabled = true, &block)
149
+ @config.instance_variable_set(
150
+ :@refresh_token_enabled,
151
+ block || enabled,
152
+ )
78
153
  end
79
154
 
80
- def use_refresh_token
81
- @config.instance_variable_set('@refresh_token_enabled', true)
155
+ # Reuse access token for the same resource owner within an application
156
+ # (disabled by default)
157
+ # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
158
+ def reuse_access_token
159
+ @config.instance_variable_set(:@reuse_access_token, true)
82
160
  end
83
161
 
84
- def realm(realm)
85
- @config.instance_variable_set('@realm', realm)
162
+ # Choose to use the url path for native autorization codes
163
+ # Enabling this flag sets the authorization code response route for
164
+ # native redirect uris to oauth/authorize/<code>. The default is
165
+ # oauth/authorize/native?code=<code>.
166
+ # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/1143
167
+ def use_url_path_for_native_authorization
168
+ @config.instance_variable_set(:@use_url_path_for_native_authorization, true)
86
169
  end
87
170
 
88
- def reuse_access_token
89
- @config.instance_variable_set("@reuse_access_token", true)
171
+ # TODO: maybe make it more generic for other flows too?
172
+ # Only allow one valid access token obtained via client credentials
173
+ # per client. If a new access token is obtained before the old one
174
+ # expired, the old one gets revoked (disabled by default)
175
+ def revoke_previous_client_credentials_token
176
+ @config.instance_variable_set(:@revoke_previous_client_credentials_token, true)
90
177
  end
91
178
 
92
- def force_ssl_in_redirect_uri(boolean)
93
- @config.instance_variable_set("@force_ssl_in_redirect_uri", boolean)
179
+ # Use an API mode for applications generated with --api argument
180
+ # It will skip applications controller, disable forgery protection
181
+ def api_only
182
+ @config.instance_variable_set(:@api_only, true)
94
183
  end
95
184
 
96
- def access_token_generator(access_token_generator)
97
- @config.instance_variable_set(
98
- '@access_token_generator', access_token_generator
99
- )
185
+ # Enables polymorphic Resource Owner association for Access Grant and
186
+ # Access Token models. Requires additional database columns to be setup.
187
+ def use_polymorphic_resource_owner
188
+ @config.instance_variable_set(:@polymorphic_resource_owner, true)
100
189
  end
101
- end
102
190
 
103
- module Option
104
- # Defines configuration option
105
- #
106
- # When you call option, it defines two methods. One method will take place
107
- # in the +Config+ class and the other method will take place in the
108
- # +Builder+ class.
109
- #
110
- # The +name+ parameter will set both builder method and config attribute.
111
- # If the +:as+ option is defined, the builder method will be the specified
112
- # option while the config attribute will be the +name+ parameter.
113
- #
114
- # If you want to introduce another level of config DSL you can
115
- # define +builder_class+ parameter.
116
- # Builder should take a block as the initializer parameter and respond to function +build+
117
- # that returns the value of the config attribute.
118
- #
119
- # ==== Options
120
- #
121
- # * [:+as+] Set the builder method that goes inside +configure+ block
122
- # * [+:default+] The default value in case no option was set
123
- #
124
- # ==== Examples
191
+ # Forbids creating/updating applications with arbitrary scopes that are
192
+ # not in configuration, i.e. `default_scopes` or `optional_scopes`.
193
+ # (disabled by default)
194
+ def enforce_configured_scopes
195
+ @config.instance_variable_set(:@enforce_configured_scopes, true)
196
+ end
197
+
198
+ # Enforce request content type as the spec requires:
199
+ # disabled by default for backward compatibility.
200
+ def enforce_content_type
201
+ @config.instance_variable_set(:@enforce_content_type, true)
202
+ end
203
+
204
+ # Allow optional hashing of input tokens before persisting them.
205
+ # Will be used for hashing of input token and grants.
125
206
  #
126
- # option :name
127
- # option :name, as: :set_name
128
- # option :name, default: 'My Name'
129
- # option :scopes builder_class: ScopesBuilder
207
+ # @param using
208
+ # Provide a different secret storage implementation class for tokens
209
+ # @param fallback
210
+ # Provide a fallback secret storage implementation class for tokens
211
+ # or use :plain to fallback to plain tokens
212
+ def hash_token_secrets(using: nil, fallback: nil)
213
+ default = "::Doorkeeper::SecretStoring::Sha256Hash"
214
+ configure_secrets_for :token,
215
+ using: using || default,
216
+ fallback: fallback
217
+ end
218
+
219
+ # Allow optional hashing of application secrets before persisting them.
220
+ # Will be used for hashing of input token and grants.
130
221
  #
131
- def option(name, options = {})
132
- attribute = options[:as] || name
133
- attribute_builder = options[:builder_class]
134
-
135
- Builder.instance_eval do
136
- define_method name do |*args, &block|
137
- # TODO: is builder_class option being used?
138
- value = unless attribute_builder
139
- block ? block : args.first
140
- else
141
- attribute_builder.new(&block).build
142
- end
143
-
144
- @config.instance_variable_set(:"@#{attribute}", value)
145
- end
146
- end
222
+ # @param using
223
+ # Provide a different secret storage implementation for applications
224
+ # @param fallback
225
+ # Provide a fallback secret storage implementation for applications
226
+ # or use :plain to fallback to plain application secrets
227
+ def hash_application_secrets(using: nil, fallback: nil)
228
+ default = "::Doorkeeper::SecretStoring::Sha256Hash"
229
+ configure_secrets_for :application,
230
+ using: using || default,
231
+ fallback: fallback
232
+ end
147
233
 
148
- define_method attribute do |*args|
149
- if instance_variable_defined?(:"@#{attribute}")
150
- instance_variable_get(:"@#{attribute}")
151
- else
152
- options[:default]
153
- end
154
- end
234
+ private
155
235
 
156
- public attribute
157
- end
236
+ # Configure the secret storing functionality
237
+ def configure_secrets_for(type, using:, fallback:)
238
+ raise ArgumentError, "Invalid type #{type}" if %i[application token].exclude?(type)
239
+
240
+ @config.instance_variable_set(:"@#{type}_secret_strategy", using.constantize)
241
+
242
+ if fallback.nil?
243
+ return
244
+ elsif fallback.to_sym == :plain
245
+ fallback = "::Doorkeeper::SecretStoring::Plain"
246
+ end
158
247
 
159
- def extended(base)
160
- base.send(:private, :option)
248
+ @config.instance_variable_set(:"@#{type}_secret_fallback_strategy", fallback.constantize)
161
249
  end
162
250
  end
163
251
 
252
+ # Replace with `default: Builder` when we drop support of Rails < 5.2
253
+ mattr_reader(:builder_class) { Builder }
254
+
164
255
  extend Option
256
+ include Validations
165
257
 
166
258
  option :resource_owner_authenticator,
167
259
  as: :authenticate_resource_owner,
168
260
  default: (lambda do |_routes|
169
- logger.warn(I18n.translate('doorkeeper.errors.messages.resource_owner_authenticator_not_configured'))
261
+ ::Rails.logger.warn(
262
+ I18n.t("doorkeeper.errors.messages.resource_owner_authenticator_not_configured"),
263
+ )
264
+
170
265
  nil
171
266
  end)
267
+
172
268
  option :admin_authenticator,
173
269
  as: :authenticate_admin,
174
- default: ->(_routes) {}
270
+ default: (lambda do |_routes|
271
+ ::Rails.logger.warn(
272
+ I18n.t("doorkeeper.errors.messages.admin_authenticator_not_configured"),
273
+ )
274
+
275
+ head :forbidden
276
+ end)
277
+
175
278
  option :resource_owner_from_credentials,
176
279
  default: (lambda do |_routes|
177
- warn(I18n.translate('doorkeeper.errors.messages.credential_flow_not_configured'))
280
+ ::Rails.logger.warn(
281
+ I18n.t("doorkeeper.errors.messages.credential_flow_not_configured"),
282
+ )
283
+
178
284
  nil
179
285
  end)
180
286
 
287
+ # Hooks for authorization
288
+ option :before_successful_authorization, default: ->(_controller, _context = nil) {}
289
+ option :after_successful_authorization, default: ->(_controller, _context = nil) {}
290
+ # Hooks for strategies responses
291
+ option :before_successful_strategy_response, default: ->(_request) {}
292
+ option :after_successful_strategy_response, default: ->(_request, _response) {}
293
+ # Allows to customize Token Introspection response
294
+ option :custom_introspection_response, default: ->(_token, _context) { {} }
295
+
181
296
  option :skip_authorization, default: ->(_routes) {}
182
297
  option :access_token_expires_in, default: 7200
183
- option :custom_access_token_expires_in, default: lambda { |_app| nil }
298
+ option :custom_access_token_expires_in, default: ->(_context) { nil }
184
299
  option :authorization_code_expires_in, default: 600
185
300
  option :orm, default: :active_record
186
- option :native_redirect_uri, default: 'urn:ietf:wg:oauth:2.0:oob'
187
- option :active_record_options, default: {}
188
- option :realm, default: 'Doorkeeper'
301
+ option :native_redirect_uri, default: "urn:ietf:wg:oauth:2.0:oob", deprecated: true
302
+ option :grant_flows, default: %w[authorization_code client_credentials]
303
+ option :handle_auth_errors, default: :render
304
+ option :token_lookup_batch_size, default: 10_000
305
+ # Sets the token_reuse_limit
306
+ # It will be used only when reuse_access_token option in enabled
307
+ # By default it will be 100
308
+ # It will be used for token reusablity to some threshold percentage
309
+ # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/1189
310
+ option :token_reuse_limit, default: 100
311
+
312
+ # Don't require client authentication for password grants. If client credentials
313
+ # are present they will still be validated, and the grant rejected if the credentials
314
+ # are invalid.
315
+ #
316
+ # This is discouraged. Spec says that password grants always require a client.
317
+ #
318
+ # See https://github.com/doorkeeper-gem/doorkeeper/issues/1412#issuecomment-632750422
319
+ # and https://github.com/doorkeeper-gem/doorkeeper/pull/1420
320
+ #
321
+ # Since many applications use this unsafe behavior in the wild, this is kept as a
322
+ # not-recommended option. You should be aware that you are not following the OAuth
323
+ # spec, and understand the security implications of doing so.
324
+ option :skip_client_authentication_for_password_grant,
325
+ default: false
326
+
327
+ # TODO: remove the option
328
+ option :active_record_options,
329
+ default: {},
330
+ deprecated: { message: "Customize Doorkeeper models instead" }
331
+
332
+ # Hook to allow arbitrary user-client authorization
333
+ option :authorize_resource_owner_for_client,
334
+ default: ->(_client, _resource_owner) { true }
335
+
336
+ # Allows to customize OAuth grant flows that +each+ application support.
337
+ # You can configure a custom block (or use a class respond to `#call`) that must
338
+ # return `true` in case Application instance supports requested OAuth grant flow
339
+ # during the authorization request to the server. This configuration +doesn't+
340
+ # set flows per application, it only allows to check if application supports
341
+ # specific grant flow.
342
+ #
343
+ # For example you can add an additional database column to `oauth_applications` table,
344
+ # say `t.array :grant_flows, default: []`, and store allowed grant flows that can
345
+ # be used with this application there. Then when authorization requested Doorkeeper
346
+ # will call this block to check if specific Application (passed with client_id and/or
347
+ # client_secret) is allowed to perform the request for the specific grant type
348
+ # (authorization, password, client_credentials, etc).
349
+ #
350
+ # Example of the block:
351
+ #
352
+ # ->(flow, client) { client.grant_flows.include?(flow) }
353
+ #
354
+ # In case this option invocation result is `false`, Doorkeeper server returns
355
+ # :unauthorized_client error and stops the request.
356
+ #
357
+ # @param allow_grant_flow_for_client [Proc] Block or any object respond to #call
358
+ # @return [Boolean] `true` if allow or `false` if forbid the request
359
+ #
360
+ option :allow_grant_flow_for_client, default: ->(_grant_flow, _client) { true }
361
+
362
+ # Allows to forbid specific Application redirect URI's by custom rules.
363
+ # Doesn't forbid any URI by default.
364
+ #
365
+ # @param forbid_redirect_uri [Proc] Block or any object respond to #call
366
+ #
367
+ option :forbid_redirect_uri, default: ->(_uri) { false }
368
+
369
+ # WWW-Authenticate Realm (default "Doorkeeper").
370
+ #
371
+ # @param realm [String] ("Doorkeeper") Authentication realm
372
+ #
373
+ option :realm, default: "Doorkeeper"
374
+
375
+ # Forces the usage of the HTTPS protocol in non-native redirect uris
376
+ # (enabled by default in non-development environments). OAuth2
377
+ # delegates security in communication to the HTTPS protocol so it is
378
+ # wise to keep this enabled.
379
+ #
380
+ # @param [Boolean] boolean_or_block value for the parameter, true by default in
381
+ # non-development environment
382
+ #
383
+ # @yield [uri] Conditional usage of SSL redirect uris.
384
+ # @yieldparam [URI] Redirect URI
385
+ # @yieldreturn [Boolean] Indicates necessity of usage of the HTTPS protocol
386
+ # in non-native redirect uris
387
+ #
189
388
  option :force_ssl_in_redirect_uri, default: !Rails.env.development?
190
- option :grant_flows, default: %w(authorization_code client_credentials)
191
- option :access_token_generator, default: "Doorkeeper::OAuth::Helpers::UniqueToken"
192
389
 
193
- attr_reader :reuse_access_token
390
+ # Use a custom class for generating the access token.
391
+ # https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-access-token-generator
392
+ #
393
+ # @param access_token_generator [String]
394
+ # the name of the access token generator class
395
+ #
396
+ option :access_token_generator,
397
+ default: "Doorkeeper::OAuth::Helpers::UniqueToken"
398
+
399
+ # Use a custom class for generating the application secret.
400
+ # https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-application-secret-generator
401
+ #
402
+ # @param application_secret_generator [String]
403
+ # the name of the application secret generator class
404
+ #
405
+ option :application_secret_generator,
406
+ default: "Doorkeeper::OAuth::Helpers::UniqueToken"
407
+
408
+ # Default access token generator is a SecureRandom class from Ruby stdlib.
409
+ # This option defines which method will be used to generate a unique token value.
410
+ #
411
+ # @param default_generator_method [Symbol]
412
+ # the method name of the default access token generator
413
+ #
414
+ option :default_generator_method, default: :urlsafe_base64
415
+
416
+ # The controller Doorkeeper::ApplicationController inherits from.
417
+ # Defaults to ActionController::Base.
418
+ # https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-controllers
419
+ #
420
+ # @param base_controller [String] the name of the base controller
421
+ option :base_controller,
422
+ default: (lambda do
423
+ api_only ? "ActionController::API" : "ActionController::Base"
424
+ end)
425
+
426
+ # The controller Doorkeeper::ApplicationMetalController inherits from.
427
+ # Defaults to ActionController::API.
428
+ #
429
+ # @param base_metal_controller [String] the name of the base controller
430
+ option :base_metal_controller,
431
+ default: "ActionController::API"
432
+
433
+ option :access_token_class,
434
+ default: "Doorkeeper::AccessToken"
435
+
436
+ option :access_grant_class,
437
+ default: "Doorkeeper::AccessGrant"
438
+
439
+ option :application_class,
440
+ default: "Doorkeeper::Application"
441
+
442
+ # Allows to set blank redirect URIs for Applications in case
443
+ # server configured to use URI-less grant flows.
444
+ #
445
+ option :allow_blank_redirect_uri,
446
+ default: (lambda do |grant_flows, _application|
447
+ grant_flows.exclude?("authorization_code") &&
448
+ grant_flows.exclude?("implicit")
449
+ end)
450
+
451
+ # Configure protection of token introspection request.
452
+ # By default this configuration allows to introspect a token by
453
+ # another token of the same application, or to introspect the token
454
+ # that belongs to authorized client, or access token has been introspected
455
+ # is a public one (doesn't belong to any client)
456
+ #
457
+ # You can define any custom rule you need or just disable token
458
+ # introspection at all.
459
+ #
460
+ # @param token [Doorkeeper::AccessToken]
461
+ # token to be introspected
462
+ #
463
+ # @param authorized_client [Doorkeeper::Application]
464
+ # authorized client (if request is authorized using Basic auth with
465
+ # Client Credentials for example)
466
+ #
467
+ # @param authorized_token [Doorkeeper::AccessToken]
468
+ # Bearer token used to authorize the request
469
+ #
470
+ option :allow_token_introspection,
471
+ default: (lambda do |token, authorized_client, authorized_token|
472
+ if authorized_token
473
+ authorized_token.application == token&.application
474
+ elsif token.application
475
+ authorized_client == token.application
476
+ else
477
+ true
478
+ end
479
+ end)
480
+
481
+ attr_reader :reuse_access_token,
482
+ :token_secret_fallback_strategy,
483
+ :application_secret_fallback_strategy
484
+
485
+ def clear_cache!
486
+ %i[
487
+ application_model
488
+ access_token_model
489
+ access_grant_model
490
+ ].each do |var|
491
+ remove_instance_variable("@#{var}") if instance_variable_defined?("@#{var}")
492
+ end
493
+ end
494
+
495
+ # Doorkeeper Access Token model class.
496
+ #
497
+ # @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
498
+ #
499
+ def access_token_model
500
+ @access_token_model ||= access_token_class.constantize
501
+ end
502
+
503
+ # Doorkeeper Access Grant model class.
504
+ #
505
+ # @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
506
+ #
507
+ def access_grant_model
508
+ @access_grant_model ||= access_grant_class.constantize
509
+ end
510
+
511
+ # Doorkeeper Application model class.
512
+ #
513
+ # @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
514
+ #
515
+ def application_model
516
+ @application_model ||= application_class.constantize
517
+ end
518
+
519
+ def api_only
520
+ @api_only ||= false
521
+ end
522
+
523
+ def enforce_content_type
524
+ @enforce_content_type ||= false
525
+ end
194
526
 
195
527
  def refresh_token_enabled?
196
- !!@refresh_token_enabled
528
+ if defined?(@refresh_token_enabled)
529
+ @refresh_token_enabled
530
+ else
531
+ false
532
+ end
533
+ end
534
+
535
+ def resolve_controller(name)
536
+ config_option = public_send(:"#{name}_controller")
537
+ controller_name = if config_option.respond_to?(:call)
538
+ instance_exec(&config_option)
539
+ else
540
+ config_option
541
+ end
542
+
543
+ controller_name.constantize
544
+ end
545
+
546
+ def revoke_previous_client_credentials_token?
547
+ option_set? :revoke_previous_client_credentials_token
548
+ end
549
+
550
+ def enforce_configured_scopes?
551
+ option_set? :enforce_configured_scopes
197
552
  end
198
553
 
199
554
  def enable_application_owner?
200
- !!@enable_application_owner
555
+ option_set? :enable_application_owner
556
+ end
557
+
558
+ def polymorphic_resource_owner?
559
+ option_set? :polymorphic_resource_owner
201
560
  end
202
561
 
203
562
  def confirm_application_owner?
204
- !!@confirm_application_owner
563
+ option_set? :confirm_application_owner
564
+ end
565
+
566
+ def raise_on_errors?
567
+ handle_auth_errors == :raise
568
+ end
569
+
570
+ def application_secret_hashed?
571
+ instance_variable_defined?(:"@application_secret_strategy")
572
+ end
573
+
574
+ def token_secret_strategy
575
+ @token_secret_strategy ||= ::Doorkeeper::SecretStoring::Plain
576
+ end
577
+
578
+ def application_secret_strategy
579
+ @application_secret_strategy ||= ::Doorkeeper::SecretStoring::Plain
205
580
  end
206
581
 
207
582
  def default_scopes
@@ -216,45 +591,130 @@ doorkeeper.
216
591
  @scopes ||= default_scopes + optional_scopes
217
592
  end
218
593
 
594
+ def scopes_by_grant_type
595
+ @scopes_by_grant_type ||= {}
596
+ end
597
+
219
598
  def client_credentials_methods
220
- @client_credentials ||= [:from_basic, :from_params]
599
+ @client_credentials_methods ||= %i[from_basic from_params]
221
600
  end
222
601
 
223
602
  def access_token_methods
224
- @access_token_methods ||= [:from_bearer_authorization, :from_access_token_param, :from_bearer_param]
603
+ @access_token_methods ||= %i[
604
+ from_bearer_authorization
605
+ from_access_token_param
606
+ from_bearer_param
607
+ ]
608
+ end
609
+
610
+ def enabled_grant_flows
611
+ @enabled_grant_flows ||= calculate_grant_flows.map { |name| Doorkeeper::GrantFlow.get(name) }.compact
225
612
  end
226
613
 
227
- def realm
228
- @realm ||= 'Doorkeeper'
614
+ def authorization_response_flows
615
+ @authorization_response_flows ||= enabled_grant_flows.select(&:handles_response_type?) +
616
+ deprecated_authorization_flows
617
+ end
618
+
619
+ def token_grant_flows
620
+ @token_grant_flows ||= calculate_token_grant_flows
229
621
  end
230
622
 
231
623
  def authorization_response_types
232
- @authorization_response_types ||= calculate_authorization_response_types
624
+ authorization_response_flows.map(&:response_type_matches)
233
625
  end
234
626
 
235
627
  def token_grant_types
236
- @token_grant_types ||= calculate_token_grant_types
628
+ token_grant_flows.map(&:grant_type_matches)
237
629
  end
238
630
 
239
- private
631
+ # [NOTE]: deprecated and will be removed soon
632
+ def deprecated_token_grant_types_resolver
633
+ @deprecated_token_grant_types ||= calculate_token_grant_types
634
+ end
635
+
636
+ def native_authorization_code_route
637
+ @use_url_path_for_native_authorization = false unless defined?(@use_url_path_for_native_authorization)
638
+ @use_url_path_for_native_authorization ? '/:code' : '/native'
639
+ end
240
640
 
241
- # Determines what values are acceptable for 'response_type' param in
242
- # authorization request endpoint, and return them as an array of strings.
243
- #
641
+ # [NOTE]: deprecated and will be removed soon
642
+ def deprecated_authorization_flows
643
+ response_types = calculate_authorization_response_types
644
+
645
+ if response_types.any?
646
+ ::Kernel.warn <<~WARNING
647
+ Please, don't patch Doorkeeper::Config#calculate_authorization_response_types method.
648
+ Register your custom grant flows using the public API:
649
+ `Doorkeeper::GrantFlow.register(grant_flow_name, **options)`.
650
+ WARNING
651
+ end
652
+
653
+ response_types.map do |response_type|
654
+ Doorkeeper::GrantFlow::FallbackFlow.new(response_type, response_type_matches: response_type)
655
+ end
656
+ end
657
+
658
+ # [NOTE]: deprecated and will be removed soon
244
659
  def calculate_authorization_response_types
245
- types = []
246
- types << 'code' if grant_flows.include? 'authorization_code'
247
- types << 'token' if grant_flows.include? 'implicit'
248
- types
660
+ []
249
661
  end
250
662
 
251
- # Determines what values are acceptable for 'grant_type' param token
252
- # request endpoint, and return them in array.
253
- #
663
+ # [NOTE]: deprecated and will be removed soon
254
664
  def calculate_token_grant_types
255
- types = grant_flows - ['implicit']
256
- types << 'refresh_token' if refresh_token_enabled?
665
+ types = grant_flows - ["implicit"]
666
+ types << "refresh_token" if refresh_token_enabled?
257
667
  types
258
668
  end
669
+
670
+ # Calculates grant flows configured by the user in Doorkeeper
671
+ # configuration considering registered aliases that is exposed
672
+ # to single or multiple other flows.
673
+ #
674
+ def calculate_grant_flows
675
+ configured_flows = grant_flows.map(&:to_s)
676
+ aliases = Doorkeeper::GrantFlow.aliases.keys.map(&:to_s)
677
+
678
+ flows = configured_flows - aliases
679
+ aliases.each do |flow_alias|
680
+ next unless configured_flows.include?(flow_alias)
681
+
682
+ flows.concat(Doorkeeper::GrantFlow.expand_alias(flow_alias))
683
+ end
684
+
685
+ flows.flatten.uniq
686
+ end
687
+
688
+ def allow_blank_redirect_uri?(application = nil)
689
+ if allow_blank_redirect_uri.respond_to?(:call)
690
+ allow_blank_redirect_uri.call(grant_flows, application)
691
+ else
692
+ allow_blank_redirect_uri
693
+ end
694
+ end
695
+
696
+ def allow_grant_flow_for_client?(grant_flow, client)
697
+ return true unless option_defined?(:allow_grant_flow_for_client)
698
+
699
+ allow_grant_flow_for_client.call(grant_flow, client)
700
+ end
701
+
702
+ def option_defined?(name)
703
+ instance_variable_defined?("@#{name}")
704
+ end
705
+
706
+ private
707
+
708
+ # Helper to read boolearized configuration option
709
+ def option_set?(instance_key)
710
+ var = instance_variable_get("@#{instance_key}")
711
+ !!(defined?(var) && var)
712
+ end
713
+
714
+ def calculate_token_grant_flows
715
+ flows = enabled_grant_flows.select(&:handles_grant_type?)
716
+ flows << Doorkeeper::GrantFlow.get("refresh_token") if refresh_token_enabled?
717
+ flows
718
+ end
259
719
  end
260
720
  end