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
@@ -1,60 +1,66 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "doorkeeper/config/abstract_builder"
3
4
  require "doorkeeper/config/option"
5
+ require "doorkeeper/config/validations"
4
6
 
5
7
  module Doorkeeper
8
+ # Defines a MissingConfiguration error for a missing Doorkeeper configuration
9
+ #
6
10
  class MissingConfiguration < StandardError
7
- # Defines a MissingConfiguration error for a missing Doorkeeper
8
- # configuration
9
11
  def initialize
10
12
  super("Configuration for doorkeeper missing. Do you have doorkeeper initializer?")
11
13
  end
12
14
  end
13
15
 
14
- def self.configure(&block)
15
- @config = Config::Builder.new(&block).build
16
- setup_orm_adapter
17
- setup_orm_models
18
- setup_application_owner if @config.enable_application_owner?
19
- @config
20
- 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
22
+
23
+ class << self
24
+ def configure(&block)
25
+ @config = Config::Builder.new(&block).build
26
+ setup_orm_adapter
27
+ setup_orm_models
28
+ setup_application_owner if @config.enable_application_owner?
29
+ @config
30
+ end
21
31
 
22
- def self.configuration
23
- @config || (raise MissingConfiguration)
24
- end
32
+ # @return [Doorkeeper::Config] configuration instance
33
+ #
34
+ def configuration
35
+ @config || (raise MissingConfiguration)
36
+ end
25
37
 
26
- def self.setup_orm_adapter
27
- @orm_adapter = "doorkeeper/orm/#{configuration.orm}".classify.constantize
28
- rescue NameError => e
29
- raise e, "ORM adapter not found (#{configuration.orm})", <<-ERROR_MSG.strip_heredoc
30
- [doorkeeper] ORM adapter not found (#{configuration.orm}), or there was an error
31
- trying to load it.
38
+ alias config configuration
32
39
 
33
- You probably need to add the related gem for this adapter to work with
34
- doorkeeper.
35
- ERROR_MSG
36
- end
40
+ def setup_orm_adapter
41
+ @orm_adapter = "doorkeeper/orm/#{configuration.orm}".classify.constantize
42
+ rescue NameError => e
43
+ raise e, "ORM adapter not found (#{configuration.orm})", <<-ERROR_MSG.strip_heredoc
44
+ [DOORKEEPER] ORM adapter not found (#{configuration.orm}), or there was an error
45
+ trying to load it.
37
46
 
38
- def self.setup_orm_models
39
- @orm_adapter.initialize_models!
40
- end
47
+ You probably need to add the related gem for this adapter to work with
48
+ doorkeeper.
49
+ ERROR_MSG
50
+ end
51
+
52
+ def setup_orm_models
53
+ @orm_adapter.initialize_models!
54
+ end
41
55
 
42
- def self.setup_application_owner
43
- @orm_adapter.initialize_application_owner!
56
+ def setup_application_owner
57
+ @orm_adapter.initialize_application_owner!
58
+ end
44
59
  end
45
60
 
46
61
  class Config
47
- class Builder
48
- def initialize(&block)
49
- @config = Config.new
50
- instance_eval(&block)
51
- end
52
-
53
- def build
54
- @config.validate
55
- @config
56
- end
57
-
62
+ # Default Doorkeeper configuration builder
63
+ class Builder < AbstractBuilder
58
64
  # Provide support for an owner to be assigned to each registered
59
65
  # application (disabled by default)
60
66
  # Optional parameter confirmation: true (default false) if you want
@@ -120,7 +126,7 @@ module Doorkeeper
120
126
  def use_refresh_token(enabled = true, &block)
121
127
  @config.instance_variable_set(
122
128
  :@refresh_token_enabled,
123
- block || enabled
129
+ block || enabled,
124
130
  )
125
131
  end
126
132
 
@@ -131,13 +137,12 @@ module Doorkeeper
131
137
  @config.instance_variable_set(:@reuse_access_token, true)
132
138
  end
133
139
 
134
- # Sets the token_reuse_limit
135
- # It will be used only when reuse_access_token option in enabled
136
- # By default it will be 100
137
- # It will be used for token reusablity to some threshold percentage
138
- # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/1189
139
- def token_reuse_limit(percentage)
140
- @config.instance_variable_set(:@token_reuse_limit, percentage)
140
+ # TODO: maybe make it more generic for other flows too?
141
+ # Only allow one valid access token obtained via client credentials
142
+ # per client. If a new access token is obtained before the old one
143
+ # expired, the old one gets revoked (disabled by default)
144
+ def revoke_previous_client_credentials_token
145
+ @config.instance_variable_set(:@revoke_previous_client_credentials_token, true)
141
146
  end
142
147
 
143
148
  # Use an API mode for applications generated with --api argument
@@ -146,6 +151,12 @@ module Doorkeeper
146
151
  @config.instance_variable_set(:@api_only, true)
147
152
  end
148
153
 
154
+ # Enables polymorphic Resource Owner association for Access Grant and
155
+ # Access Token models. Requires additional database columns to be setup.
156
+ def use_polymorphic_resource_owner
157
+ @config.instance_variable_set(:@polymorphic_resource_owner, true)
158
+ end
159
+
149
160
  # Forbids creating/updating applications with arbitrary scopes that are
150
161
  # not in configuration, i.e. `default_scopes` or `optional_scopes`.
151
162
  # (disabled by default)
@@ -195,8 +206,7 @@ module Doorkeeper
195
206
  def configure_secrets_for(type, using:, fallback:)
196
207
  raise ArgumentError, "Invalid type #{type}" if %i[application token].exclude?(type)
197
208
 
198
- @config.instance_variable_set(:"@#{type}_secret_strategy",
199
- using.constantize)
209
+ @config.instance_variable_set(:"@#{type}_secret_strategy", using.constantize)
200
210
 
201
211
  if fallback.nil?
202
212
  return
@@ -204,18 +214,21 @@ module Doorkeeper
204
214
  fallback = "::Doorkeeper::SecretStoring::Plain"
205
215
  end
206
216
 
207
- @config.instance_variable_set(:"@#{type}_secret_fallback_strategy",
208
- fallback.constantize)
217
+ @config.instance_variable_set(:"@#{type}_secret_fallback_strategy", fallback.constantize)
209
218
  end
210
219
  end
211
220
 
221
+ # Replace with `default: Builder` when we drop support of Rails < 5.2
222
+ mattr_reader(:builder_class) { Builder }
223
+
212
224
  extend Option
225
+ include Validations
213
226
 
214
227
  option :resource_owner_authenticator,
215
228
  as: :authenticate_resource_owner,
216
229
  default: (lambda do |_routes|
217
230
  ::Rails.logger.warn(
218
- I18n.t("doorkeeper.errors.messages.resource_owner_authenticator_not_configured")
231
+ I18n.t("doorkeeper.errors.messages.resource_owner_authenticator_not_configured"),
219
232
  )
220
233
 
221
234
  nil
@@ -225,7 +238,7 @@ module Doorkeeper
225
238
  as: :authenticate_admin,
226
239
  default: (lambda do |_routes|
227
240
  ::Rails.logger.warn(
228
- I18n.t("doorkeeper.errors.messages.admin_authenticator_not_configured")
241
+ I18n.t("doorkeeper.errors.messages.admin_authenticator_not_configured"),
229
242
  )
230
243
 
231
244
  head :forbidden
@@ -234,15 +247,15 @@ module Doorkeeper
234
247
  option :resource_owner_from_credentials,
235
248
  default: (lambda do |_routes|
236
249
  ::Rails.logger.warn(
237
- I18n.t("doorkeeper.errors.messages.credential_flow_not_configured")
250
+ I18n.t("doorkeeper.errors.messages.credential_flow_not_configured"),
238
251
  )
239
252
 
240
253
  nil
241
254
  end)
242
255
 
243
256
  # Hooks for authorization
244
- option :before_successful_authorization, default: ->(_context) {}
245
- option :after_successful_authorization, default: ->(_context) {}
257
+ option :before_successful_authorization, default: ->(_controller, _context = nil) {}
258
+ option :after_successful_authorization, default: ->(_controller, _context = nil) {}
246
259
  # Hooks for strategies responses
247
260
  option :before_successful_strategy_response, default: ->(_request) {}
248
261
  option :after_successful_strategy_response, default: ->(_request, _response) {}
@@ -255,9 +268,38 @@ module Doorkeeper
255
268
  option :authorization_code_expires_in, default: 600
256
269
  option :orm, default: :active_record
257
270
  option :native_redirect_uri, default: "urn:ietf:wg:oauth:2.0:oob", deprecated: true
258
- option :active_record_options, default: {}
259
271
  option :grant_flows, default: %w[authorization_code client_credentials]
260
272
  option :handle_auth_errors, default: :render
273
+ option :token_lookup_batch_size, default: 10_000
274
+ # Sets the token_reuse_limit
275
+ # It will be used only when reuse_access_token option in enabled
276
+ # By default it will be 100
277
+ # It will be used for token reusablity to some threshold percentage
278
+ # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/1189
279
+ option :token_reuse_limit, default: 100
280
+
281
+ # Don't require client authentication for password grants. If client credentials
282
+ # are present they will still be validated, and the grant rejected if the credentials
283
+ # are invalid.
284
+ #
285
+ # This is discouraged. Spec says that password grants always require a client.
286
+ #
287
+ # See https://github.com/doorkeeper-gem/doorkeeper/issues/1412#issuecomment-632750422
288
+ # and https://github.com/doorkeeper-gem/doorkeeper/pull/1420
289
+ #
290
+ # Since many applications use this unsafe behavior in the wild, this is kept as a
291
+ # not-recommended option. You should be aware that you are not following the OAuth
292
+ # spec, and understand the security implications of doing so.
293
+ option :skip_client_authentication_for_password_grant,
294
+ default: false
295
+
296
+ option :active_record_options,
297
+ default: {},
298
+ deprecated: { message: "Customize Doorkeeper models instead" }
299
+
300
+ # Hook to allow arbitrary user-client authorization
301
+ option :authorize_resource_owner_for_client,
302
+ default: ->(_client, _resource_owner) { true }
261
303
 
262
304
  # Allows to customize OAuth grant flows that +each+ application support.
263
305
  # You can configure a custom block (or use a class respond to `#call`) that must
@@ -332,7 +374,7 @@ module Doorkeeper
332
374
 
333
375
  # The controller Doorkeeper::ApplicationController inherits from.
334
376
  # Defaults to ActionController::Base.
335
- # https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-base-controller
377
+ # https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-controllers
336
378
  #
337
379
  # @param base_controller [String] the name of the base controller
338
380
  option :base_controller,
@@ -347,6 +389,15 @@ module Doorkeeper
347
389
  option :base_metal_controller,
348
390
  default: "ActionController::API"
349
391
 
392
+ option :access_token_class,
393
+ default: "Doorkeeper::AccessToken"
394
+
395
+ option :access_grant_class,
396
+ default: "Doorkeeper::AccessGrant"
397
+
398
+ option :application_class,
399
+ default: "Doorkeeper::Application"
400
+
350
401
  # Allows to set blank redirect URIs for Applications in case
351
402
  # server configured to use URI-less grant flows.
352
403
  #
@@ -386,17 +437,32 @@ module Doorkeeper
386
437
  end
387
438
  end)
388
439
 
389
- attr_reader :api_only,
390
- :enforce_content_type,
391
- :reuse_access_token,
440
+ attr_reader :reuse_access_token,
392
441
  :token_secret_fallback_strategy,
393
442
  :application_secret_fallback_strategy
394
443
 
395
- # Return the valid subset of this configuration
396
- def validate
397
- validate_reuse_access_token_value
398
- validate_token_reuse_limit
399
- validate_secret_strategies
444
+ # Doorkeeper Access Token model class.
445
+ #
446
+ # @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
447
+ #
448
+ def access_token_model
449
+ @access_token_model ||= access_token_class.constantize
450
+ end
451
+
452
+ # Doorkeeper Access Grant model class.
453
+ #
454
+ # @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
455
+ #
456
+ def access_grant_model
457
+ @access_grant_model ||= access_grant_class.constantize
458
+ end
459
+
460
+ # Doorkeeper Application model class.
461
+ #
462
+ # @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
463
+ #
464
+ def application_model
465
+ @application_model ||= application_class.constantize
400
466
  end
401
467
 
402
468
  def api_only
@@ -415,10 +481,6 @@ module Doorkeeper
415
481
  end
416
482
  end
417
483
 
418
- def token_reuse_limit
419
- @token_reuse_limit ||= 100
420
- end
421
-
422
484
  def resolve_controller(name)
423
485
  config_option = public_send(:"#{name}_controller")
424
486
  controller_name = if config_option.respond_to?(:call)
@@ -430,6 +492,10 @@ module Doorkeeper
430
492
  controller_name.constantize
431
493
  end
432
494
 
495
+ def revoke_previous_client_credentials_token?
496
+ option_set? :revoke_previous_client_credentials_token
497
+ end
498
+
433
499
  def enforce_configured_scopes?
434
500
  option_set? :enforce_configured_scopes
435
501
  end
@@ -438,6 +504,10 @@ module Doorkeeper
438
504
  option_set? :enable_application_owner
439
505
  end
440
506
 
507
+ def polymorphic_resource_owner?
508
+ option_set? :polymorphic_resource_owner
509
+ end
510
+
441
511
  def confirm_application_owner?
442
512
  option_set? :confirm_application_owner
443
513
  end
@@ -446,6 +516,10 @@ module Doorkeeper
446
516
  handle_auth_errors == :raise
447
517
  end
448
518
 
519
+ def application_secret_hashed?
520
+ instance_variable_defined?(:"@application_secret_strategy")
521
+ end
522
+
449
523
  def token_secret_strategy
450
524
  @token_secret_strategy ||= ::Doorkeeper::SecretStoring::Plain
451
525
  end
@@ -482,12 +556,77 @@ module Doorkeeper
482
556
  ]
483
557
  end
484
558
 
559
+ def enabled_grant_flows
560
+ @enabled_grant_flows ||= calculate_grant_flows.map { |name| Doorkeeper::GrantFlow.get(name) }.compact
561
+ end
562
+
563
+ def authorization_response_flows
564
+ @authorization_response_flows ||= enabled_grant_flows.select(&:handles_response_type?) +
565
+ deprecated_authorization_flows
566
+ end
567
+
568
+ def token_grant_flows
569
+ @token_grant_flows ||= calculate_token_grant_flows
570
+ end
571
+
485
572
  def authorization_response_types
486
- @authorization_response_types ||= calculate_authorization_response_types.freeze
573
+ authorization_response_flows.map(&:response_type_matches)
487
574
  end
488
575
 
489
576
  def token_grant_types
490
- @token_grant_types ||= calculate_token_grant_types.freeze
577
+ token_grant_flows.map(&:grant_type_matches)
578
+ end
579
+
580
+ # [NOTE]: deprecated and will be removed soon
581
+ def deprecated_token_grant_types_resolver
582
+ @deprecated_token_grant_types ||= calculate_token_grant_types
583
+ end
584
+
585
+ # [NOTE]: deprecated and will be removed soon
586
+ def deprecated_authorization_flows
587
+ response_types = calculate_authorization_response_types
588
+
589
+ if response_types.any?
590
+ ::Kernel.warn <<~WARNING
591
+ Please, don't patch Doorkeeper::Config#calculate_authorization_response_types method.
592
+ Register your custom grant flows using the public API:
593
+ `Doorkeeper::GrantFlow.register(grant_flow_name, **options)`.
594
+ WARNING
595
+ end
596
+
597
+ response_types.map do |response_type|
598
+ Doorkeeper::GrantFlow::FallbackFlow.new(response_type, response_type_matches: response_type)
599
+ end
600
+ end
601
+
602
+ # [NOTE]: deprecated and will be removed soon
603
+ def calculate_authorization_response_types
604
+ []
605
+ end
606
+
607
+ # [NOTE]: deprecated and will be removed soon
608
+ def calculate_token_grant_types
609
+ types = grant_flows - ["implicit"]
610
+ types << "refresh_token" if refresh_token_enabled?
611
+ types
612
+ end
613
+
614
+ # Calculates grant flows configured by the user in Doorkeeper
615
+ # configuration considering registered aliases that is exposed
616
+ # to single or multiple other flows.
617
+ #
618
+ def calculate_grant_flows
619
+ configured_flows = grant_flows.map(&:to_s)
620
+ aliases = Doorkeeper::GrantFlow.aliases.keys.map(&:to_s)
621
+
622
+ flows = configured_flows - aliases
623
+ aliases.each do |flow_alias|
624
+ next unless configured_flows.include?(flow_alias)
625
+
626
+ flows.concat(Doorkeeper::GrantFlow.expand_alias(flow_alias))
627
+ end
628
+
629
+ flows.flatten.uniq
491
630
  end
492
631
 
493
632
  def allow_blank_redirect_uri?(application = nil)
@@ -516,57 +655,10 @@ module Doorkeeper
516
655
  !!(defined?(var) && var)
517
656
  end
518
657
 
519
- # Determines what values are acceptable for 'response_type' param in
520
- # authorization request endpoint, and return them as an array of strings.
521
- #
522
- def calculate_authorization_response_types
523
- types = []
524
- types << "code" if grant_flows.include? "authorization_code"
525
- types << "token" if grant_flows.include? "implicit"
526
- types
527
- end
528
-
529
- # Determines what values are acceptable for 'grant_type' param token
530
- # request endpoint, and return them in array.
531
- #
532
- def calculate_token_grant_types
533
- types = grant_flows - ["implicit"]
534
- types << "refresh_token" if refresh_token_enabled?
535
- types
536
- end
537
-
538
- # Determine whether +reuse_access_token+ and a non-restorable
539
- # +token_secret_strategy+ have both been activated.
540
- #
541
- # In that case, disable reuse_access_token value and warn the user.
542
- def validate_reuse_access_token_value
543
- strategy = token_secret_strategy
544
- return if !reuse_access_token || strategy.allows_restoring_secrets?
545
-
546
- ::Rails.logger.warn(
547
- "You have configured both reuse_access_token " \
548
- "AND strategy strategy '#{strategy}' that cannot restore tokens. " \
549
- "This combination is unsupported. reuse_access_token will be disabled"
550
- )
551
- @reuse_access_token = false
552
- end
553
-
554
- # Validate that the provided strategies are valid for
555
- # tokens and applications
556
- def validate_secret_strategies
557
- token_secret_strategy.validate_for :token
558
- application_secret_strategy.validate_for :application
559
- end
560
-
561
- def validate_token_reuse_limit
562
- return if !reuse_access_token ||
563
- (token_reuse_limit > 0 && token_reuse_limit <= 100)
564
-
565
- ::Rails.logger.warn(
566
- "You have configured an invalid value for token_reuse_limit option. " \
567
- "It will be set to default 100"
568
- )
569
- @token_reuse_limit = 100
658
+ def calculate_token_grant_flows
659
+ flows = enabled_grant_flows.select(&:handles_grant_type?)
660
+ flows << Doorkeeper::GrantFlow.get("refresh_token") if refresh_token_enabled?
661
+ flows
570
662
  end
571
663
  end
572
664
  end
@@ -4,7 +4,7 @@ module Doorkeeper
4
4
  class Engine < Rails::Engine
5
5
  initializer "doorkeeper.params.filter" do |app|
6
6
  parameters = %w[client_secret code authentication_token access_token refresh_token]
7
- app.config.filter_parameters << /^(#{Regexp.union parameters})$/
7
+ app.config.filter_parameters << /^(#{Regexp.union(parameters)})$/
8
8
  end
9
9
 
10
10
  initializer "doorkeeper.routes" do
@@ -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
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module GrantFlow
5
+ module Registry
6
+ mattr_accessor :flows
7
+ self.flows = {}
8
+
9
+ mattr_accessor :aliases
10
+ self.aliases = {}
11
+
12
+ # Allows to register custom OAuth grant flow so that Doorkeeper
13
+ # could recognize and process it.
14
+ #
15
+ def register(name_or_flow, **options)
16
+ unless name_or_flow.is_a?(Doorkeeper::GrantFlow::Flow)
17
+ name_or_flow = Flow.new(name_or_flow, **options)
18
+ end
19
+
20
+ flow_key = name_or_flow.name.to_sym
21
+
22
+ if flows.key?(flow_key)
23
+ ::Kernel.warn <<~WARNING
24
+ [DOORKEEPER] '#{flow_key}' grant flow already registered and will be overridden
25
+ in #{caller(1..1).first}
26
+ WARNING
27
+ end
28
+
29
+ flows[flow_key] = name_or_flow
30
+ end
31
+
32
+ # Allows to register aliases that could be used in `grant_flows`
33
+ # configuration option. It is possible to have aliases like 1:1 or
34
+ # 1:N, i.e. "implicit_oidc" => ['token', 'id_token', 'id_token token'].
35
+ #
36
+ def register_alias(alias_name, **options)
37
+ aliases[alias_name.to_sym] = Array.wrap(options.fetch(:as))
38
+ end
39
+
40
+ def expand_alias(alias_name)
41
+ aliases.fetch(alias_name.to_sym, [])
42
+ end
43
+
44
+ # [NOTE]: make it to use #fetch after removing fallbacks
45
+ def get(name)
46
+ flows[name.to_sym]
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "doorkeeper/grant_flow/flow"
4
+ require "doorkeeper/grant_flow/fallback_flow"
5
+ require "doorkeeper/grant_flow/registry"
6
+
7
+ module Doorkeeper
8
+ module GrantFlow
9
+ extend Registry
10
+
11
+ register(
12
+ :implicit,
13
+ response_type_matches: "token",
14
+ response_mode_matches: %w[fragment form_post],
15
+ response_type_strategy: Doorkeeper::Request::Token,
16
+ )
17
+
18
+ register(
19
+ :authorization_code,
20
+ response_type_matches: "code",
21
+ response_mode_matches: %w[query fragment form_post],
22
+ response_type_strategy: Doorkeeper::Request::Code,
23
+ grant_type_matches: "authorization_code",
24
+ grant_type_strategy: Doorkeeper::Request::AuthorizationCode,
25
+ )
26
+
27
+ register(
28
+ :client_credentials,
29
+ grant_type_matches: "client_credentials",
30
+ grant_type_strategy: Doorkeeper::Request::ClientCredentials,
31
+ )
32
+
33
+ register(
34
+ :password,
35
+ grant_type_matches: "password",
36
+ grant_type_strategy: Doorkeeper::Request::Password,
37
+ )
38
+
39
+ register(
40
+ :refresh_token,
41
+ grant_type_matches: "refresh_token",
42
+ grant_type_strategy: Doorkeeper::Request::RefreshToken,
43
+ )
44
+ end
45
+ end
@@ -18,7 +18,7 @@ module Doorkeeper
18
18
 
19
19
  scopes = if endpoint_scopes
20
20
  Doorkeeper::OAuth::Scopes.from_array(endpoint_scopes)
21
- elsif scopes && !scopes.empty?
21
+ elsif scopes.present?
22
22
  Doorkeeper::OAuth::Scopes.from_array(scopes)
23
23
  end
24
24
 
@@ -39,7 +39,7 @@ module Doorkeeper
39
39
  def doorkeeper_token
40
40
  @doorkeeper_token ||= OAuth::Token.authenticate(
41
41
  decorated_request,
42
- *Doorkeeper.configuration.access_token_methods
42
+ *Doorkeeper.config.access_token_methods,
43
43
  )
44
44
  end
45
45