doorkeeper 5.1.0 → 5.5.1

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} +242 -25
  3. data/README.md +21 -11
  4. data/app/controllers/doorkeeper/application_controller.rb +3 -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 +6 -6
  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 +295 -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 +34 -11
  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 +3 -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 +2 -6
  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 +45 -312
  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,65 @@ 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
+ # 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 }
303
+
304
+ # Allows to customize OAuth grant flows that +each+ application support.
305
+ # You can configure a custom block (or use a class respond to `#call`) that must
306
+ # return `true` in case Application instance supports requested OAuth grant flow
307
+ # during the authorization request to the server. This configuration +doesn't+
308
+ # set flows per application, it only allows to check if application supports
309
+ # specific grant flow.
310
+ #
311
+ # For example you can add an additional database column to `oauth_applications` table,
312
+ # say `t.array :grant_flows, default: []`, and store allowed grant flows that can
313
+ # be used with this application there. Then when authorization requested Doorkeeper
314
+ # will call this block to check if specific Application (passed with client_id and/or
315
+ # client_secret) is allowed to perform the request for the specific grant type
316
+ # (authorization, password, client_credentials, etc).
317
+ #
318
+ # Example of the block:
319
+ #
320
+ # ->(flow, client) { client.grant_flows.include?(flow) }
321
+ #
322
+ # In case this option invocation result is `false`, Doorkeeper server returns
323
+ # :unauthorized_client error and stops the request.
324
+ #
325
+ # @param allow_grant_flow_for_client [Proc] Block or any object respond to #call
326
+ # @return [Boolean] `true` if allow or `false` if forbid the request
327
+ #
328
+ option :allow_grant_flow_for_client, default: ->(_grant_flow, _client) { true }
261
329
 
262
330
  # Allows to forbid specific Application redirect URI's by custom rules.
263
331
  # Doesn't forbid any URI by default.
@@ -288,7 +356,7 @@ module Doorkeeper
288
356
  option :force_ssl_in_redirect_uri, default: !Rails.env.development?
289
357
 
290
358
  # Use a custom class for generating the access token.
291
- # https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
359
+ # https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-access-token-generator
292
360
  #
293
361
  # @param access_token_generator [String]
294
362
  # the name of the access token generator class
@@ -306,11 +374,29 @@ module Doorkeeper
306
374
 
307
375
  # The controller Doorkeeper::ApplicationController inherits from.
308
376
  # Defaults to ActionController::Base.
309
- # https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
377
+ # https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-base-controller
310
378
  #
311
379
  # @param base_controller [String] the name of the base controller
312
380
  option :base_controller,
313
- default: "ActionController::Base"
381
+ default: (lambda do
382
+ api_only ? "ActionController::API" : "ActionController::Base"
383
+ end)
384
+
385
+ # The controller Doorkeeper::ApplicationMetalController inherits from.
386
+ # Defaults to ActionController::API.
387
+ #
388
+ # @param base_metal_controller [String] the name of the base controller
389
+ option :base_metal_controller,
390
+ default: "ActionController::API"
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"
314
400
 
315
401
  # Allows to set blank redirect URIs for Applications in case
316
402
  # server configured to use URI-less grant flows.
@@ -321,17 +407,62 @@ module Doorkeeper
321
407
  grant_flows.exclude?("implicit")
322
408
  end)
323
409
 
324
- attr_reader :api_only,
325
- :enforce_content_type,
326
- :reuse_access_token,
410
+ # Configure protection of token introspection request.
411
+ # By default this configuration allows to introspect a token by
412
+ # another token of the same application, or to introspect the token
413
+ # that belongs to authorized client, or access token has been introspected
414
+ # is a public one (doesn't belong to any client)
415
+ #
416
+ # You can define any custom rule you need or just disable token
417
+ # introspection at all.
418
+ #
419
+ # @param token [Doorkeeper::AccessToken]
420
+ # token to be introspected
421
+ #
422
+ # @param authorized_client [Doorkeeper::Application]
423
+ # authorized client (if request is authorized using Basic auth with
424
+ # Client Credentials for example)
425
+ #
426
+ # @param authorized_token [Doorkeeper::AccessToken]
427
+ # Bearer token used to authorize the request
428
+ #
429
+ option :allow_token_introspection,
430
+ default: (lambda do |token, authorized_client, authorized_token|
431
+ if authorized_token
432
+ authorized_token.application == token&.application
433
+ elsif token.application
434
+ authorized_client == token.application
435
+ else
436
+ true
437
+ end
438
+ end)
439
+
440
+ attr_reader :reuse_access_token,
327
441
  :token_secret_fallback_strategy,
328
442
  :application_secret_fallback_strategy
329
443
 
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
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
335
466
  end
336
467
 
337
468
  def api_only
@@ -350,8 +481,19 @@ module Doorkeeper
350
481
  end
351
482
  end
352
483
 
353
- def token_reuse_limit
354
- @token_reuse_limit ||= 100
484
+ def resolve_controller(name)
485
+ config_option = public_send(:"#{name}_controller")
486
+ controller_name = if config_option.respond_to?(:call)
487
+ instance_exec(&config_option)
488
+ else
489
+ config_option
490
+ end
491
+
492
+ controller_name.constantize
493
+ end
494
+
495
+ def revoke_previous_client_credentials_token?
496
+ option_set? :revoke_previous_client_credentials_token
355
497
  end
356
498
 
357
499
  def enforce_configured_scopes?
@@ -362,6 +504,10 @@ module Doorkeeper
362
504
  option_set? :enable_application_owner
363
505
  end
364
506
 
507
+ def polymorphic_resource_owner?
508
+ option_set? :polymorphic_resource_owner
509
+ end
510
+
365
511
  def confirm_application_owner?
366
512
  option_set? :confirm_application_owner
367
513
  end
@@ -370,6 +516,10 @@ module Doorkeeper
370
516
  handle_auth_errors == :raise
371
517
  end
372
518
 
519
+ def application_secret_hashed?
520
+ instance_variable_defined?(:"@application_secret_strategy")
521
+ end
522
+
373
523
  def token_secret_strategy
374
524
  @token_secret_strategy ||= ::Doorkeeper::SecretStoring::Plain
375
525
  end
@@ -406,85 +556,109 @@ module Doorkeeper
406
556
  ]
407
557
  end
408
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
+
409
572
  def authorization_response_types
410
- @authorization_response_types ||= calculate_authorization_response_types.freeze
573
+ authorization_response_flows.map(&:response_type_matches)
411
574
  end
412
575
 
413
576
  def token_grant_types
414
- @token_grant_types ||= calculate_token_grant_types.freeze
577
+ token_grant_flows.map(&:grant_type_matches)
415
578
  end
416
579
 
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
580
+ # [NOTE]: deprecated and will be removed soon
581
+ def deprecated_token_grant_types_resolver
582
+ @deprecated_token_grant_types ||= calculate_token_grant_types
423
583
  end
424
584
 
425
- def option_defined?(name)
426
- instance_variable_defined?("@#{name}")
427
- end
585
+ # [NOTE]: deprecated and will be removed soon
586
+ def deprecated_authorization_flows
587
+ response_types = calculate_authorization_response_types
428
588
 
429
- private
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
430
596
 
431
- # Helper to read boolearized configuration option
432
- def option_set?(instance_key)
433
- var = instance_variable_get("@#{instance_key}")
434
- !!(defined?(var) && var)
597
+ response_types.map do |response_type|
598
+ Doorkeeper::GrantFlow::FallbackFlow.new(response_type, response_type_matches: response_type)
599
+ end
435
600
  end
436
601
 
437
- # Determines what values are acceptable for 'response_type' param in
438
- # authorization request endpoint, and return them as an array of strings.
439
- #
602
+ # [NOTE]: deprecated and will be removed soon
440
603
  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
604
+ []
445
605
  end
446
606
 
447
- # Determines what values are acceptable for 'grant_type' param token
448
- # request endpoint, and return them in array.
449
- #
607
+ # [NOTE]: deprecated and will be removed soon
450
608
  def calculate_token_grant_types
451
609
  types = grant_flows - ["implicit"]
452
610
  types << "refresh_token" if refresh_token_enabled?
453
611
  types
454
612
  end
455
613
 
456
- # Determine whether +reuse_access_token+ and a non-restorable
457
- # +token_secret_strategy+ have both been activated.
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.
458
617
  #
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?
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
630
+ end
631
+
632
+ def allow_blank_redirect_uri?(application = nil)
633
+ if allow_blank_redirect_uri.respond_to?(:call)
634
+ allow_blank_redirect_uri.call(grant_flows, application)
635
+ else
636
+ allow_blank_redirect_uri
637
+ end
638
+ end
639
+
640
+ def allow_grant_flow_for_client?(grant_flow, client)
641
+ return true unless option_defined?(:allow_grant_flow_for_client)
463
642
 
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
643
+ allow_grant_flow_for_client.call(grant_flow, client)
470
644
  end
471
645
 
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
646
+ def option_defined?(name)
647
+ instance_variable_defined?("@#{name}")
477
648
  end
478
649
 
479
- def validate_token_reuse_limit
480
- return if !reuse_access_token ||
481
- (token_reuse_limit > 0 && token_reuse_limit <= 100)
650
+ private
651
+
652
+ # Helper to read boolearized configuration option
653
+ def option_set?(instance_key)
654
+ var = instance_variable_get("@#{instance_key}")
655
+ !!(defined?(var) && var)
656
+ end
482
657
 
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
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
488
662
  end
489
663
  end
490
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
@@ -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