doorkeeper 5.1.0 → 5.5.0

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

Potentially problematic release.


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

Files changed (265) hide show
  1. checksums.yaml +4 -4
  2. data/{NEWS.md → CHANGELOG.md} +234 -25
  3. data/README.md +21 -11
  4. data/app/controllers/doorkeeper/application_controller.rb +2 -2
  5. data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
  6. data/app/controllers/doorkeeper/applications_controller.rb +8 -7
  7. data/app/controllers/doorkeeper/authorizations_controller.rb +56 -19
  8. data/app/controllers/doorkeeper/authorized_applications_controller.rb +5 -5
  9. data/app/controllers/doorkeeper/token_info_controller.rb +12 -2
  10. data/app/controllers/doorkeeper/tokens_controller.rb +93 -25
  11. data/app/views/doorkeeper/applications/_form.html.erb +1 -7
  12. data/app/views/doorkeeper/applications/show.html.erb +35 -14
  13. data/app/views/doorkeeper/authorizations/form_post.html.erb +11 -0
  14. data/config/locales/en.yml +13 -3
  15. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  16. data/lib/doorkeeper/config/option.rb +20 -2
  17. data/lib/doorkeeper/config/validations.rb +53 -0
  18. data/lib/doorkeeper/config.rb +291 -121
  19. data/lib/doorkeeper/engine.rb +1 -1
  20. data/lib/doorkeeper/errors.rb +13 -18
  21. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  22. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  23. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  24. data/lib/doorkeeper/grant_flow.rb +45 -0
  25. data/lib/doorkeeper/grape/helpers.rb +7 -3
  26. data/lib/doorkeeper/helpers/controller.rb +36 -11
  27. data/lib/doorkeeper/models/access_grant_mixin.rb +22 -18
  28. data/lib/doorkeeper/models/access_token_mixin.rb +194 -51
  29. data/lib/doorkeeper/models/application_mixin.rb +8 -7
  30. data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
  31. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  32. data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
  33. data/lib/doorkeeper/models/concerns/revocable.rb +1 -28
  34. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  35. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  36. data/lib/doorkeeper/oauth/authorization/code.rb +25 -14
  37. data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
  38. data/lib/doorkeeper/oauth/authorization/token.rb +24 -19
  39. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  40. data/lib/doorkeeper/oauth/authorization_code_request.rb +40 -21
  41. data/lib/doorkeeper/oauth/base_request.rb +21 -23
  42. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  43. data/lib/doorkeeper/oauth/client.rb +8 -9
  44. data/lib/doorkeeper/oauth/client_credentials/creator.rb +45 -5
  45. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +10 -8
  46. data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +13 -3
  47. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  48. data/lib/doorkeeper/oauth/code_request.rb +6 -12
  49. data/lib/doorkeeper/oauth/code_response.rb +24 -14
  50. data/lib/doorkeeper/oauth/error.rb +1 -1
  51. data/lib/doorkeeper/oauth/error_response.rb +10 -11
  52. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +8 -12
  53. data/lib/doorkeeper/oauth/helpers/unique_token.rb +8 -5
  54. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +19 -5
  55. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  56. data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
  57. data/lib/doorkeeper/oauth/invalid_token_response.rb +7 -4
  58. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  59. data/lib/doorkeeper/oauth/password_access_token_request.rb +32 -10
  60. data/lib/doorkeeper/oauth/pre_authorization.rb +111 -42
  61. data/lib/doorkeeper/oauth/refresh_token_request.rb +45 -33
  62. data/lib/doorkeeper/oauth/token.rb +6 -7
  63. data/lib/doorkeeper/oauth/token_introspection.rb +24 -18
  64. data/lib/doorkeeper/oauth/token_request.rb +6 -20
  65. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  66. data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
  67. data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
  68. data/lib/doorkeeper/orm/active_record/application.rb +5 -83
  69. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +68 -0
  70. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +59 -0
  71. data/lib/doorkeeper/orm/active_record/mixins/application.rb +198 -0
  72. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
  73. data/lib/doorkeeper/orm/active_record.rb +20 -6
  74. data/lib/doorkeeper/rails/helpers.rb +4 -4
  75. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  76. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  77. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  78. data/lib/doorkeeper/rails/routes.rb +17 -25
  79. data/lib/doorkeeper/rake/db.rake +6 -6
  80. data/lib/doorkeeper/rake/setup.rake +5 -0
  81. data/lib/doorkeeper/request/authorization_code.rb +5 -3
  82. data/lib/doorkeeper/request/client_credentials.rb +2 -2
  83. data/lib/doorkeeper/request/password.rb +2 -2
  84. data/lib/doorkeeper/request/refresh_token.rb +5 -4
  85. data/lib/doorkeeper/request/strategy.rb +2 -2
  86. data/lib/doorkeeper/request.rb +49 -17
  87. data/lib/doorkeeper/server.rb +7 -11
  88. data/lib/doorkeeper/stale_records_cleaner.rb +6 -2
  89. data/lib/doorkeeper/version.rb +1 -5
  90. data/lib/doorkeeper.rb +114 -79
  91. data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
  92. data/lib/generators/doorkeeper/confidential_applications_generator.rb +2 -2
  93. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  94. data/lib/generators/doorkeeper/migration_generator.rb +1 -1
  95. data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
  96. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +7 -7
  97. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +3 -1
  98. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  99. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  100. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  101. data/lib/generators/doorkeeper/templates/initializer.rb +205 -43
  102. data/lib/generators/doorkeeper/templates/migration.rb.erb +18 -6
  103. metadata +43 -310
  104. data/.coveralls.yml +0 -1
  105. data/.github/ISSUE_TEMPLATE.md +0 -25
  106. data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  107. data/.gitignore +0 -20
  108. data/.gitlab-ci.yml +0 -16
  109. data/.hound.yml +0 -3
  110. data/.rspec +0 -1
  111. data/.rubocop.yml +0 -50
  112. data/.travis.yml +0 -35
  113. data/Appraisals +0 -40
  114. data/CODE_OF_CONDUCT.md +0 -46
  115. data/CONTRIBUTING.md +0 -47
  116. data/Dangerfile +0 -67
  117. data/Gemfile +0 -24
  118. data/RELEASING.md +0 -10
  119. data/Rakefile +0 -28
  120. data/SECURITY.md +0 -15
  121. data/UPGRADE.md +0 -2
  122. data/app/validators/redirect_uri_validator.rb +0 -50
  123. data/bin/console +0 -16
  124. data/doorkeeper.gemspec +0 -34
  125. data/gemfiles/rails_5_0.gemfile +0 -17
  126. data/gemfiles/rails_5_1.gemfile +0 -17
  127. data/gemfiles/rails_5_2.gemfile +0 -17
  128. data/gemfiles/rails_6_0.gemfile +0 -17
  129. data/gemfiles/rails_master.gemfile +0 -17
  130. data/spec/controllers/application_metal_controller_spec.rb +0 -64
  131. data/spec/controllers/applications_controller_spec.rb +0 -180
  132. data/spec/controllers/authorizations_controller_spec.rb +0 -527
  133. data/spec/controllers/protected_resources_controller_spec.rb +0 -353
  134. data/spec/controllers/token_info_controller_spec.rb +0 -50
  135. data/spec/controllers/tokens_controller_spec.rb +0 -330
  136. data/spec/dummy/Rakefile +0 -9
  137. data/spec/dummy/app/assets/config/manifest.js +0 -2
  138. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  139. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
  140. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
  141. data/spec/dummy/app/controllers/home_controller.rb +0 -18
  142. data/spec/dummy/app/controllers/metal_controller.rb +0 -13
  143. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
  144. data/spec/dummy/app/helpers/application_helper.rb +0 -7
  145. data/spec/dummy/app/models/user.rb +0 -7
  146. data/spec/dummy/app/views/home/index.html.erb +0 -0
  147. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  148. data/spec/dummy/config/application.rb +0 -47
  149. data/spec/dummy/config/boot.rb +0 -7
  150. data/spec/dummy/config/database.yml +0 -15
  151. data/spec/dummy/config/environment.rb +0 -5
  152. data/spec/dummy/config/environments/development.rb +0 -31
  153. data/spec/dummy/config/environments/production.rb +0 -64
  154. data/spec/dummy/config/environments/test.rb +0 -45
  155. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
  156. data/spec/dummy/config/initializers/doorkeeper.rb +0 -121
  157. data/spec/dummy/config/initializers/secret_token.rb +0 -10
  158. data/spec/dummy/config/initializers/session_store.rb +0 -10
  159. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  160. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  161. data/spec/dummy/config/routes.rb +0 -13
  162. data/spec/dummy/config.ru +0 -6
  163. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  164. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  165. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
  166. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  167. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  168. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
  169. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
  170. data/spec/dummy/db/schema.rb +0 -68
  171. data/spec/dummy/public/404.html +0 -26
  172. data/spec/dummy/public/422.html +0 -26
  173. data/spec/dummy/public/500.html +0 -26
  174. data/spec/dummy/public/favicon.ico +0 -0
  175. data/spec/dummy/script/rails +0 -9
  176. data/spec/factories.rb +0 -30
  177. data/spec/generators/application_owner_generator_spec.rb +0 -28
  178. data/spec/generators/confidential_applications_generator_spec.rb +0 -29
  179. data/spec/generators/install_generator_spec.rb +0 -36
  180. data/spec/generators/migration_generator_spec.rb +0 -28
  181. data/spec/generators/pkce_generator_spec.rb +0 -28
  182. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
  183. data/spec/generators/templates/routes.rb +0 -4
  184. data/spec/generators/views_generator_spec.rb +0 -29
  185. data/spec/grape/grape_integration_spec.rb +0 -137
  186. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
  187. data/spec/lib/config_spec.rb +0 -697
  188. data/spec/lib/doorkeeper_spec.rb +0 -27
  189. data/spec/lib/models/expirable_spec.rb +0 -61
  190. data/spec/lib/models/reusable_spec.rb +0 -40
  191. data/spec/lib/models/revocable_spec.rb +0 -59
  192. data/spec/lib/models/scopes_spec.rb +0 -53
  193. data/spec/lib/models/secret_storable_spec.rb +0 -135
  194. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
  195. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -156
  196. data/spec/lib/oauth/base_request_spec.rb +0 -205
  197. data/spec/lib/oauth/base_response_spec.rb +0 -47
  198. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  199. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -94
  200. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
  201. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
  202. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -29
  203. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -109
  204. data/spec/lib/oauth/client_spec.rb +0 -38
  205. data/spec/lib/oauth/code_request_spec.rb +0 -47
  206. data/spec/lib/oauth/code_response_spec.rb +0 -36
  207. data/spec/lib/oauth/error_response_spec.rb +0 -66
  208. data/spec/lib/oauth/error_spec.rb +0 -23
  209. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -22
  210. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -98
  211. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
  212. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -247
  213. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -55
  214. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -192
  215. data/spec/lib/oauth/pre_authorization_spec.rb +0 -215
  216. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -177
  217. data/spec/lib/oauth/scopes_spec.rb +0 -148
  218. data/spec/lib/oauth/token_request_spec.rb +0 -150
  219. data/spec/lib/oauth/token_response_spec.rb +0 -86
  220. data/spec/lib/oauth/token_spec.rb +0 -158
  221. data/spec/lib/request/strategy_spec.rb +0 -54
  222. data/spec/lib/secret_storing/base_spec.rb +0 -60
  223. data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
  224. data/spec/lib/secret_storing/plain_spec.rb +0 -44
  225. data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
  226. data/spec/lib/server_spec.rb +0 -61
  227. data/spec/lib/stale_records_cleaner_spec.rb +0 -89
  228. data/spec/models/doorkeeper/access_grant_spec.rb +0 -144
  229. data/spec/models/doorkeeper/access_token_spec.rb +0 -591
  230. data/spec/models/doorkeeper/application_spec.rb +0 -367
  231. data/spec/requests/applications/applications_request_spec.rb +0 -259
  232. data/spec/requests/applications/authorized_applications_spec.rb +0 -32
  233. data/spec/requests/endpoints/authorization_spec.rb +0 -73
  234. data/spec/requests/endpoints/token_spec.rb +0 -75
  235. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -78
  236. data/spec/requests/flows/authorization_code_spec.rb +0 -447
  237. data/spec/requests/flows/client_credentials_spec.rb +0 -128
  238. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -34
  239. data/spec/requests/flows/implicit_grant_spec.rb +0 -90
  240. data/spec/requests/flows/password_spec.rb +0 -259
  241. data/spec/requests/flows/refresh_token_spec.rb +0 -233
  242. data/spec/requests/flows/revoke_token_spec.rb +0 -143
  243. data/spec/requests/flows/skip_authorization_spec.rb +0 -66
  244. data/spec/requests/protected_resources/metal_spec.rb +0 -16
  245. data/spec/requests/protected_resources/private_api_spec.rb +0 -83
  246. data/spec/routing/custom_controller_routes_spec.rb +0 -133
  247. data/spec/routing/default_routes_spec.rb +0 -41
  248. data/spec/routing/scoped_routes_spec.rb +0 -47
  249. data/spec/spec_helper.rb +0 -57
  250. data/spec/spec_helper_integration.rb +0 -4
  251. data/spec/support/dependencies/factory_bot.rb +0 -4
  252. data/spec/support/doorkeeper_rspec.rb +0 -22
  253. data/spec/support/helpers/access_token_request_helper.rb +0 -13
  254. data/spec/support/helpers/authorization_request_helper.rb +0 -43
  255. data/spec/support/helpers/config_helper.rb +0 -11
  256. data/spec/support/helpers/model_helper.rb +0 -78
  257. data/spec/support/helpers/request_spec_helper.rb +0 -98
  258. data/spec/support/helpers/url_helper.rb +0 -62
  259. data/spec/support/http_method_shim.rb +0 -29
  260. data/spec/support/orm/active_record.rb +0 -5
  261. data/spec/support/shared/controllers_shared_context.rb +0 -123
  262. data/spec/support/shared/hashing_shared_context.rb +0 -36
  263. data/spec/support/shared/models_shared_examples.rb +0 -54
  264. data/spec/validators/redirect_uri_validator_spec.rb +0 -158
  265. 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 => error
29
- raise error, "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) {}
@@ -254,10 +267,61 @@ module Doorkeeper
254
267
  option :custom_access_token_expires_in, default: ->(_context) { nil }
255
268
  option :authorization_code_expires_in, default: 600
256
269
  option :orm, default: :active_record
257
- option :native_redirect_uri, default: "urn:ietf:wg:oauth:2.0:oob"
258
- option :active_record_options, default: {}
270
+ option :native_redirect_uri, default: "urn:ietf:wg:oauth:2.0:oob", deprecated: true
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
+ # 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
+
292
+ option :active_record_options,
293
+ default: {},
294
+ deprecated: { message: "Customize Doorkeeper models instead" }
295
+
296
+ # Hook to allow arbitrary user-client authorization
297
+ option :authorize_resource_owner_for_client,
298
+ default: ->(_client, _resource_owner) { true }
299
+
300
+ # Allows to customize OAuth grant flows that +each+ application support.
301
+ # You can configure a custom block (or use a class respond to `#call`) that must
302
+ # return `true` in case Application instance supports requested OAuth grant flow
303
+ # during the authorization request to the server. This configuration +doesn't+
304
+ # set flows per application, it only allows to check if application supports
305
+ # specific grant flow.
306
+ #
307
+ # For example you can add an additional database column to `oauth_applications` table,
308
+ # say `t.array :grant_flows, default: []`, and store allowed grant flows that can
309
+ # be used with this application there. Then when authorization requested Doorkeeper
310
+ # will call this block to check if specific Application (passed with client_id and/or
311
+ # client_secret) is allowed to perform the request for the specific grant type
312
+ # (authorization, password, client_credentials, etc).
313
+ #
314
+ # Example of the block:
315
+ #
316
+ # ->(flow, client) { client.grant_flows.include?(flow) }
317
+ #
318
+ # In case this option invocation result is `false`, Doorkeeper server returns
319
+ # :unauthorized_client error and stops the request.
320
+ #
321
+ # @param allow_grant_flow_for_client [Proc] Block or any object respond to #call
322
+ # @return [Boolean] `true` if allow or `false` if forbid the request
323
+ #
324
+ option :allow_grant_flow_for_client, default: ->(_grant_flow, _client) { true }
261
325
 
262
326
  # Allows to forbid specific Application redirect URI's by custom rules.
263
327
  # Doesn't forbid any URI by default.
@@ -288,7 +352,7 @@ module Doorkeeper
288
352
  option :force_ssl_in_redirect_uri, default: !Rails.env.development?
289
353
 
290
354
  # Use a custom class for generating the access token.
291
- # https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
355
+ # https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-access-token-generator
292
356
  #
293
357
  # @param access_token_generator [String]
294
358
  # the name of the access token generator class
@@ -306,11 +370,29 @@ module Doorkeeper
306
370
 
307
371
  # The controller Doorkeeper::ApplicationController inherits from.
308
372
  # Defaults to ActionController::Base.
309
- # https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
373
+ # https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-base-controller
310
374
  #
311
375
  # @param base_controller [String] the name of the base controller
312
376
  option :base_controller,
313
- default: "ActionController::Base"
377
+ default: (lambda do
378
+ api_only ? "ActionController::API" : "ActionController::Base"
379
+ end)
380
+
381
+ # The controller Doorkeeper::ApplicationMetalController inherits from.
382
+ # Defaults to ActionController::API.
383
+ #
384
+ # @param base_metal_controller [String] the name of the base controller
385
+ option :base_metal_controller,
386
+ default: "ActionController::API"
387
+
388
+ option :access_token_class,
389
+ default: "Doorkeeper::AccessToken"
390
+
391
+ option :access_grant_class,
392
+ default: "Doorkeeper::AccessGrant"
393
+
394
+ option :application_class,
395
+ default: "Doorkeeper::Application"
314
396
 
315
397
  # Allows to set blank redirect URIs for Applications in case
316
398
  # server configured to use URI-less grant flows.
@@ -321,17 +403,62 @@ module Doorkeeper
321
403
  grant_flows.exclude?("implicit")
322
404
  end)
323
405
 
324
- attr_reader :api_only,
325
- :enforce_content_type,
326
- :reuse_access_token,
406
+ # Configure protection of token introspection request.
407
+ # By default this configuration allows to introspect a token by
408
+ # another token of the same application, or to introspect the token
409
+ # that belongs to authorized client, or access token has been introspected
410
+ # is a public one (doesn't belong to any client)
411
+ #
412
+ # You can define any custom rule you need or just disable token
413
+ # introspection at all.
414
+ #
415
+ # @param token [Doorkeeper::AccessToken]
416
+ # token to be introspected
417
+ #
418
+ # @param authorized_client [Doorkeeper::Application]
419
+ # authorized client (if request is authorized using Basic auth with
420
+ # Client Credentials for example)
421
+ #
422
+ # @param authorized_token [Doorkeeper::AccessToken]
423
+ # Bearer token used to authorize the request
424
+ #
425
+ option :allow_token_introspection,
426
+ default: (lambda do |token, authorized_client, authorized_token|
427
+ if authorized_token
428
+ authorized_token.application == token&.application
429
+ elsif token.application
430
+ authorized_client == token.application
431
+ else
432
+ true
433
+ end
434
+ end)
435
+
436
+ attr_reader :reuse_access_token,
327
437
  :token_secret_fallback_strategy,
328
438
  :application_secret_fallback_strategy
329
439
 
330
- # Return the valid subset of this configuration
331
- def validate
332
- validate_reuse_access_token_value
333
- validate_token_reuse_limit
334
- validate_secret_strategies
440
+ # Doorkeeper Access Token model class.
441
+ #
442
+ # @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
443
+ #
444
+ def access_token_model
445
+ @access_token_model ||= access_token_class.constantize
446
+ end
447
+
448
+ # Doorkeeper Access Grant model class.
449
+ #
450
+ # @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
451
+ #
452
+ def access_grant_model
453
+ @access_grant_model ||= access_grant_class.constantize
454
+ end
455
+
456
+ # Doorkeeper Application model class.
457
+ #
458
+ # @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
459
+ #
460
+ def application_model
461
+ @application_model ||= application_class.constantize
335
462
  end
336
463
 
337
464
  def api_only
@@ -350,8 +477,19 @@ module Doorkeeper
350
477
  end
351
478
  end
352
479
 
353
- def token_reuse_limit
354
- @token_reuse_limit ||= 100
480
+ def resolve_controller(name)
481
+ config_option = public_send(:"#{name}_controller")
482
+ controller_name = if config_option.respond_to?(:call)
483
+ instance_exec(&config_option)
484
+ else
485
+ config_option
486
+ end
487
+
488
+ controller_name.constantize
489
+ end
490
+
491
+ def revoke_previous_client_credentials_token?
492
+ option_set? :revoke_previous_client_credentials_token
355
493
  end
356
494
 
357
495
  def enforce_configured_scopes?
@@ -362,6 +500,10 @@ module Doorkeeper
362
500
  option_set? :enable_application_owner
363
501
  end
364
502
 
503
+ def polymorphic_resource_owner?
504
+ option_set? :polymorphic_resource_owner
505
+ end
506
+
365
507
  def confirm_application_owner?
366
508
  option_set? :confirm_application_owner
367
509
  end
@@ -370,6 +512,10 @@ module Doorkeeper
370
512
  handle_auth_errors == :raise
371
513
  end
372
514
 
515
+ def application_secret_hashed?
516
+ instance_variable_defined?(:"@application_secret_strategy")
517
+ end
518
+
373
519
  def token_secret_strategy
374
520
  @token_secret_strategy ||= ::Doorkeeper::SecretStoring::Plain
375
521
  end
@@ -406,85 +552,109 @@ module Doorkeeper
406
552
  ]
407
553
  end
408
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
+
409
568
  def authorization_response_types
410
- @authorization_response_types ||= calculate_authorization_response_types.freeze
569
+ authorization_response_flows.map(&:response_type_matches)
411
570
  end
412
571
 
413
572
  def token_grant_types
414
- @token_grant_types ||= calculate_token_grant_types.freeze
573
+ token_grant_flows.map(&:grant_type_matches)
415
574
  end
416
575
 
417
- def allow_blank_redirect_uri?(application = nil)
418
- if allow_blank_redirect_uri.respond_to?(:call)
419
- allow_blank_redirect_uri.call(grant_flows, application)
420
- else
421
- allow_blank_redirect_uri
422
- end
576
+ # [NOTE]: deprecated and will be removed soon
577
+ def deprecated_token_grant_types_resolver
578
+ @deprecated_token_grant_types ||= calculate_token_grant_types
423
579
  end
424
580
 
425
- def option_defined?(name)
426
- instance_variable_defined?("@#{name}")
427
- end
581
+ # [NOTE]: deprecated and will be removed soon
582
+ def deprecated_authorization_flows
583
+ response_types = calculate_authorization_response_types
428
584
 
429
- private
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
430
592
 
431
- # Helper to read boolearized configuration option
432
- def option_set?(instance_key)
433
- var = instance_variable_get("@#{instance_key}")
434
- !!(defined?(var) && var)
593
+ response_types.map do |response_type|
594
+ Doorkeeper::GrantFlow::FallbackFlow.new(response_type, response_type_matches: response_type)
595
+ end
435
596
  end
436
597
 
437
- # Determines what values are acceptable for 'response_type' param in
438
- # authorization request endpoint, and return them as an array of strings.
439
- #
598
+ # [NOTE]: deprecated and will be removed soon
440
599
  def calculate_authorization_response_types
441
- types = []
442
- types << "code" if grant_flows.include? "authorization_code"
443
- types << "token" if grant_flows.include? "implicit"
444
- types
600
+ []
445
601
  end
446
602
 
447
- # Determines what values are acceptable for 'grant_type' param token
448
- # request endpoint, and return them in array.
449
- #
603
+ # [NOTE]: deprecated and will be removed soon
450
604
  def calculate_token_grant_types
451
605
  types = grant_flows - ["implicit"]
452
606
  types << "refresh_token" if refresh_token_enabled?
453
607
  types
454
608
  end
455
609
 
456
- # Determine whether +reuse_access_token+ and a non-restorable
457
- # +token_secret_strategy+ have both been activated.
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.
458
613
  #
459
- # In that case, disable reuse_access_token value and warn the user.
460
- def validate_reuse_access_token_value
461
- strategy = token_secret_strategy
462
- return if !reuse_access_token || strategy.allows_restoring_secrets?
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
626
+ end
627
+
628
+ def allow_blank_redirect_uri?(application = nil)
629
+ if allow_blank_redirect_uri.respond_to?(:call)
630
+ allow_blank_redirect_uri.call(grant_flows, application)
631
+ else
632
+ allow_blank_redirect_uri
633
+ end
634
+ end
635
+
636
+ def allow_grant_flow_for_client?(grant_flow, client)
637
+ return true unless option_defined?(:allow_grant_flow_for_client)
463
638
 
464
- ::Rails.logger.warn(
465
- "You have configured both reuse_access_token " \
466
- "AND strategy strategy '#{strategy}' that cannot restore tokens. " \
467
- "This combination is unsupported. reuse_access_token will be disabled"
468
- )
469
- @reuse_access_token = false
639
+ allow_grant_flow_for_client.call(grant_flow, client)
470
640
  end
471
641
 
472
- # Validate that the provided strategies are valid for
473
- # tokens and applications
474
- def validate_secret_strategies
475
- token_secret_strategy.validate_for :token
476
- application_secret_strategy.validate_for :application
642
+ def option_defined?(name)
643
+ instance_variable_defined?("@#{name}")
477
644
  end
478
645
 
479
- def validate_token_reuse_limit
480
- return if !reuse_access_token ||
481
- (token_reuse_limit > 0 && token_reuse_limit <= 100)
646
+ private
647
+
648
+ # Helper to read boolearized configuration option
649
+ def option_set?(instance_key)
650
+ var = instance_variable_get("@#{instance_key}")
651
+ !!(defined?(var) && var)
652
+ end
482
653
 
483
- ::Rails.logger.warn(
484
- "You have configured an invalid value for token_reuse_limit option. " \
485
- "It will be set to default 100"
486
- )
487
- @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
488
658
  end
489
659
  end
490
660
  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
@@ -8,18 +8,6 @@ module Doorkeeper
8
8
  end
9
9
  end
10
10
 
11
- class InvalidAuthorizationStrategy < DoorkeeperError
12
- def type
13
- :unsupported_response_type
14
- end
15
- end
16
-
17
- class InvalidTokenReuse < DoorkeeperError
18
- def type
19
- :invalid_request
20
- end
21
- end
22
-
23
11
  class InvalidGrantReuse < DoorkeeperError
24
12
  def type
25
13
  :invalid_grant
@@ -32,7 +20,14 @@ module Doorkeeper
32
20
  end
33
21
  end
34
22
 
35
- class MissingRequestStrategy < DoorkeeperError
23
+ class MissingRequiredParameter < DoorkeeperError
24
+ attr_reader :missing_param
25
+
26
+ def initialize(missing_param)
27
+ super
28
+ @missing_param = missing_param
29
+ end
30
+
36
31
  def type
37
32
  :invalid_request
38
33
  end
@@ -50,10 +45,10 @@ module Doorkeeper
50
45
  TokenGeneratorNotFound = Class.new(DoorkeeperError)
51
46
  NoOrmCleaner = Class.new(DoorkeeperError)
52
47
 
53
- InvalidToken = Class.new BaseResponseError
54
- TokenExpired = Class.new InvalidToken
55
- TokenRevoked = Class.new InvalidToken
56
- TokenUnknown = Class.new InvalidToken
57
- TokenForbidden = Class.new InvalidToken
48
+ InvalidToken = Class.new(BaseResponseError)
49
+ TokenExpired = Class.new(InvalidToken)
50
+ TokenRevoked = Class.new(InvalidToken)
51
+ TokenUnknown = Class.new(InvalidToken)
52
+ TokenForbidden = Class.new(InvalidToken)
58
53
  end
59
54
  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