doorkeeper 5.1.2 → 5.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. checksums.yaml +4 -4
  2. data/{NEWS.md → CHANGELOG.md} +314 -27
  3. data/README.md +39 -22
  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 +5 -4
  7. data/app/controllers/doorkeeper/authorizations_controller.rb +76 -25
  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 +99 -28
  11. data/app/helpers/doorkeeper/dashboard_helper.rb +1 -1
  12. data/app/views/doorkeeper/applications/_form.html.erb +1 -7
  13. data/app/views/doorkeeper/applications/show.html.erb +35 -14
  14. data/app/views/doorkeeper/authorizations/error.html.erb +3 -1
  15. data/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
  16. data/app/views/doorkeeper/authorizations/new.html.erb +16 -14
  17. data/config/locales/en.yml +16 -3
  18. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  19. data/lib/doorkeeper/config/option.rb +20 -2
  20. data/lib/doorkeeper/config/validations.rb +53 -0
  21. data/lib/doorkeeper/config.rb +300 -136
  22. data/lib/doorkeeper/engine.rb +10 -3
  23. data/lib/doorkeeper/errors.rb +13 -18
  24. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  25. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  26. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  27. data/lib/doorkeeper/grant_flow.rb +45 -0
  28. data/lib/doorkeeper/grape/helpers.rb +7 -3
  29. data/lib/doorkeeper/helpers/controller.rb +36 -11
  30. data/lib/doorkeeper/models/access_grant_mixin.rb +23 -19
  31. data/lib/doorkeeper/models/access_token_mixin.rb +195 -52
  32. data/lib/doorkeeper/models/application_mixin.rb +8 -7
  33. data/lib/doorkeeper/models/concerns/expirable.rb +1 -1
  34. data/lib/doorkeeper/models/concerns/expiration_time_sql_math.rb +88 -0
  35. data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
  36. data/lib/doorkeeper/models/concerns/polymorphic_resource_owner.rb +30 -0
  37. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  38. data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
  39. data/lib/doorkeeper/models/concerns/revocable.rb +1 -28
  40. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  41. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  42. data/lib/doorkeeper/oauth/authorization/code.rb +31 -14
  43. data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
  44. data/lib/doorkeeper/oauth/authorization/token.rb +30 -19
  45. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  46. data/lib/doorkeeper/oauth/authorization_code_request.rb +51 -22
  47. data/lib/doorkeeper/oauth/base_request.rb +21 -22
  48. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  49. data/lib/doorkeeper/oauth/client.rb +8 -9
  50. data/lib/doorkeeper/oauth/client_credentials/creator.rb +42 -5
  51. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +10 -8
  52. data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +14 -5
  53. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  54. data/lib/doorkeeper/oauth/code_request.rb +6 -12
  55. data/lib/doorkeeper/oauth/code_response.rb +24 -14
  56. data/lib/doorkeeper/oauth/error.rb +1 -1
  57. data/lib/doorkeeper/oauth/error_response.rb +11 -13
  58. data/lib/doorkeeper/oauth/forbidden_token_response.rb +2 -1
  59. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +8 -12
  60. data/lib/doorkeeper/oauth/helpers/unique_token.rb +10 -7
  61. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +19 -23
  62. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  63. data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
  64. data/lib/doorkeeper/oauth/invalid_token_response.rb +7 -4
  65. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  66. data/lib/doorkeeper/oauth/password_access_token_request.rb +34 -11
  67. data/lib/doorkeeper/oauth/pre_authorization.rb +114 -44
  68. data/lib/doorkeeper/oauth/refresh_token_request.rb +54 -34
  69. data/lib/doorkeeper/oauth/token.rb +6 -7
  70. data/lib/doorkeeper/oauth/token_introspection.rb +28 -22
  71. data/lib/doorkeeper/oauth/token_request.rb +6 -20
  72. data/lib/doorkeeper/oauth/token_response.rb +2 -3
  73. data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
  74. data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
  75. data/lib/doorkeeper/orm/active_record/application.rb +5 -149
  76. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +63 -0
  77. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +77 -0
  78. data/lib/doorkeeper/orm/active_record/mixins/application.rb +210 -0
  79. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
  80. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +5 -2
  81. data/lib/doorkeeper/orm/active_record.rb +29 -22
  82. data/lib/doorkeeper/rails/helpers.rb +4 -4
  83. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  84. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  85. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  86. data/lib/doorkeeper/rails/routes.rb +28 -27
  87. data/lib/doorkeeper/rake/db.rake +6 -6
  88. data/lib/doorkeeper/request/authorization_code.rb +5 -3
  89. data/lib/doorkeeper/request/client_credentials.rb +2 -2
  90. data/lib/doorkeeper/request/password.rb +3 -2
  91. data/lib/doorkeeper/request/refresh_token.rb +5 -4
  92. data/lib/doorkeeper/request/strategy.rb +2 -2
  93. data/lib/doorkeeper/request.rb +49 -17
  94. data/lib/doorkeeper/server.rb +7 -11
  95. data/lib/doorkeeper/stale_records_cleaner.rb +6 -2
  96. data/lib/doorkeeper/version.rb +2 -6
  97. data/lib/doorkeeper.rb +183 -80
  98. data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
  99. data/lib/generators/doorkeeper/confidential_applications_generator.rb +2 -2
  100. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  101. data/lib/generators/doorkeeper/migration_generator.rb +1 -1
  102. data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
  103. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +7 -7
  104. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +3 -1
  105. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  106. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  107. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  108. data/lib/generators/doorkeeper/templates/initializer.rb +230 -50
  109. data/lib/generators/doorkeeper/templates/migration.rb.erb +31 -9
  110. metadata +61 -327
  111. data/.coveralls.yml +0 -1
  112. data/.github/ISSUE_TEMPLATE.md +0 -25
  113. data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  114. data/.gitignore +0 -20
  115. data/.gitlab-ci.yml +0 -16
  116. data/.hound.yml +0 -3
  117. data/.rspec +0 -1
  118. data/.rubocop.yml +0 -50
  119. data/.travis.yml +0 -35
  120. data/Appraisals +0 -40
  121. data/CODE_OF_CONDUCT.md +0 -46
  122. data/CONTRIBUTING.md +0 -47
  123. data/Dangerfile +0 -67
  124. data/Gemfile +0 -24
  125. data/RELEASING.md +0 -10
  126. data/Rakefile +0 -28
  127. data/SECURITY.md +0 -15
  128. data/UPGRADE.md +0 -2
  129. data/app/validators/redirect_uri_validator.rb +0 -50
  130. data/bin/console +0 -16
  131. data/doorkeeper.gemspec +0 -34
  132. data/gemfiles/rails_5_0.gemfile +0 -17
  133. data/gemfiles/rails_5_1.gemfile +0 -17
  134. data/gemfiles/rails_5_2.gemfile +0 -17
  135. data/gemfiles/rails_6_0.gemfile +0 -17
  136. data/gemfiles/rails_master.gemfile +0 -17
  137. data/spec/controllers/application_metal_controller_spec.rb +0 -64
  138. data/spec/controllers/applications_controller_spec.rb +0 -180
  139. data/spec/controllers/authorizations_controller_spec.rb +0 -527
  140. data/spec/controllers/protected_resources_controller_spec.rb +0 -353
  141. data/spec/controllers/token_info_controller_spec.rb +0 -50
  142. data/spec/controllers/tokens_controller_spec.rb +0 -330
  143. data/spec/dummy/Rakefile +0 -9
  144. data/spec/dummy/app/assets/config/manifest.js +0 -2
  145. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  146. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
  147. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
  148. data/spec/dummy/app/controllers/home_controller.rb +0 -18
  149. data/spec/dummy/app/controllers/metal_controller.rb +0 -13
  150. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
  151. data/spec/dummy/app/helpers/application_helper.rb +0 -7
  152. data/spec/dummy/app/models/user.rb +0 -7
  153. data/spec/dummy/app/views/home/index.html.erb +0 -0
  154. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  155. data/spec/dummy/config/application.rb +0 -47
  156. data/spec/dummy/config/boot.rb +0 -7
  157. data/spec/dummy/config/database.yml +0 -15
  158. data/spec/dummy/config/environment.rb +0 -5
  159. data/spec/dummy/config/environments/development.rb +0 -31
  160. data/spec/dummy/config/environments/production.rb +0 -64
  161. data/spec/dummy/config/environments/test.rb +0 -45
  162. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
  163. data/spec/dummy/config/initializers/doorkeeper.rb +0 -121
  164. data/spec/dummy/config/initializers/secret_token.rb +0 -10
  165. data/spec/dummy/config/initializers/session_store.rb +0 -10
  166. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  167. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  168. data/spec/dummy/config/routes.rb +0 -13
  169. data/spec/dummy/config.ru +0 -6
  170. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  171. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  172. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
  173. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  174. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  175. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
  176. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
  177. data/spec/dummy/db/schema.rb +0 -68
  178. data/spec/dummy/public/404.html +0 -26
  179. data/spec/dummy/public/422.html +0 -26
  180. data/spec/dummy/public/500.html +0 -26
  181. data/spec/dummy/public/favicon.ico +0 -0
  182. data/spec/dummy/script/rails +0 -9
  183. data/spec/factories.rb +0 -30
  184. data/spec/generators/application_owner_generator_spec.rb +0 -28
  185. data/spec/generators/confidential_applications_generator_spec.rb +0 -29
  186. data/spec/generators/install_generator_spec.rb +0 -36
  187. data/spec/generators/migration_generator_spec.rb +0 -28
  188. data/spec/generators/pkce_generator_spec.rb +0 -28
  189. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
  190. data/spec/generators/templates/routes.rb +0 -4
  191. data/spec/generators/views_generator_spec.rb +0 -29
  192. data/spec/grape/grape_integration_spec.rb +0 -137
  193. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
  194. data/spec/lib/config_spec.rb +0 -697
  195. data/spec/lib/doorkeeper_spec.rb +0 -27
  196. data/spec/lib/models/expirable_spec.rb +0 -61
  197. data/spec/lib/models/reusable_spec.rb +0 -40
  198. data/spec/lib/models/revocable_spec.rb +0 -59
  199. data/spec/lib/models/scopes_spec.rb +0 -53
  200. data/spec/lib/models/secret_storable_spec.rb +0 -135
  201. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
  202. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -156
  203. data/spec/lib/oauth/base_request_spec.rb +0 -205
  204. data/spec/lib/oauth/base_response_spec.rb +0 -47
  205. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  206. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -94
  207. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
  208. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
  209. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -29
  210. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -109
  211. data/spec/lib/oauth/client_spec.rb +0 -38
  212. data/spec/lib/oauth/code_request_spec.rb +0 -47
  213. data/spec/lib/oauth/code_response_spec.rb +0 -36
  214. data/spec/lib/oauth/error_response_spec.rb +0 -66
  215. data/spec/lib/oauth/error_spec.rb +0 -23
  216. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -22
  217. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -98
  218. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
  219. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -247
  220. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -55
  221. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -192
  222. data/spec/lib/oauth/pre_authorization_spec.rb +0 -215
  223. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -177
  224. data/spec/lib/oauth/scopes_spec.rb +0 -148
  225. data/spec/lib/oauth/token_request_spec.rb +0 -150
  226. data/spec/lib/oauth/token_response_spec.rb +0 -86
  227. data/spec/lib/oauth/token_spec.rb +0 -158
  228. data/spec/lib/request/strategy_spec.rb +0 -54
  229. data/spec/lib/secret_storing/base_spec.rb +0 -60
  230. data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
  231. data/spec/lib/secret_storing/plain_spec.rb +0 -44
  232. data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
  233. data/spec/lib/server_spec.rb +0 -61
  234. data/spec/lib/stale_records_cleaner_spec.rb +0 -89
  235. data/spec/models/doorkeeper/access_grant_spec.rb +0 -144
  236. data/spec/models/doorkeeper/access_token_spec.rb +0 -591
  237. data/spec/models/doorkeeper/application_spec.rb +0 -472
  238. data/spec/requests/applications/applications_request_spec.rb +0 -259
  239. data/spec/requests/applications/authorized_applications_spec.rb +0 -32
  240. data/spec/requests/endpoints/authorization_spec.rb +0 -73
  241. data/spec/requests/endpoints/token_spec.rb +0 -75
  242. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -78
  243. data/spec/requests/flows/authorization_code_spec.rb +0 -447
  244. data/spec/requests/flows/client_credentials_spec.rb +0 -128
  245. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -34
  246. data/spec/requests/flows/implicit_grant_spec.rb +0 -90
  247. data/spec/requests/flows/password_spec.rb +0 -259
  248. data/spec/requests/flows/refresh_token_spec.rb +0 -233
  249. data/spec/requests/flows/revoke_token_spec.rb +0 -143
  250. data/spec/requests/flows/skip_authorization_spec.rb +0 -66
  251. data/spec/requests/protected_resources/metal_spec.rb +0 -16
  252. data/spec/requests/protected_resources/private_api_spec.rb +0 -83
  253. data/spec/routing/custom_controller_routes_spec.rb +0 -133
  254. data/spec/routing/default_routes_spec.rb +0 -41
  255. data/spec/routing/scoped_routes_spec.rb +0 -47
  256. data/spec/spec_helper.rb +0 -57
  257. data/spec/spec_helper_integration.rb +0 -4
  258. data/spec/support/dependencies/factory_bot.rb +0 -4
  259. data/spec/support/doorkeeper_rspec.rb +0 -22
  260. data/spec/support/helpers/access_token_request_helper.rb +0 -13
  261. data/spec/support/helpers/authorization_request_helper.rb +0 -43
  262. data/spec/support/helpers/config_helper.rb +0 -11
  263. data/spec/support/helpers/model_helper.rb +0 -78
  264. data/spec/support/helpers/request_spec_helper.rb +0 -98
  265. data/spec/support/helpers/url_helper.rb +0 -62
  266. data/spec/support/http_method_shim.rb +0 -29
  267. data/spec/support/orm/active_record.rb +0 -5
  268. data/spec/support/shared/controllers_shared_context.rb +0 -123
  269. data/spec/support/shared/hashing_shared_context.rb +0 -36
  270. data/spec/support/shared/models_shared_examples.rb +0 -54
  271. data/spec/validators/redirect_uri_validator_spec.rb +0 -158
  272. data/spec/version/version_spec.rb +0 -17
@@ -1,60 +1,18 @@
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
6
- class MissingConfiguration < StandardError
7
- # Defines a MissingConfiguration error for a missing Doorkeeper
8
- # configuration
9
- def initialize
10
- super("Configuration for doorkeeper missing. Do you have doorkeeper initializer?")
11
- end
12
- end
13
-
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
21
-
22
- def self.configuration
23
- @config || (raise MissingConfiguration)
24
- end
25
-
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.
32
-
33
- You probably need to add the related gem for this adapter to work with
34
- doorkeeper.
35
- ERROR_MSG
36
- end
37
-
38
- def self.setup_orm_models
39
- @orm_adapter.initialize_models!
40
- end
41
-
42
- def self.setup_application_owner
43
- @orm_adapter.initialize_application_owner!
44
- end
45
-
8
+ # Doorkeeper option DSL could be reused in extensions to build their own
9
+ # configurations. To use the Option DSL gems need to define `builder_class` method
10
+ # that returns configuration Builder class. This exception raises when they don't
11
+ # define it.
12
+ #
46
13
  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
-
14
+ # Default Doorkeeper configuration builder
15
+ class Builder < AbstractBuilder
58
16
  # Provide support for an owner to be assigned to each registered
59
17
  # application (disabled by default)
60
18
  # Optional parameter confirmation: true (default false) if you want
@@ -120,7 +78,7 @@ module Doorkeeper
120
78
  def use_refresh_token(enabled = true, &block)
121
79
  @config.instance_variable_set(
122
80
  :@refresh_token_enabled,
123
- block || enabled
81
+ block || enabled,
124
82
  )
125
83
  end
126
84
 
@@ -131,13 +89,21 @@ module Doorkeeper
131
89
  @config.instance_variable_set(:@reuse_access_token, true)
132
90
  end
133
91
 
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)
92
+ # Choose to use the url path for native autorization codes
93
+ # Enabling this flag sets the authorization code response route for
94
+ # native redirect uris to oauth/authorize/<code>. The default is
95
+ # oauth/authorize/native?code=<code>.
96
+ # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/1143
97
+ def use_url_path_for_native_authorization
98
+ @config.instance_variable_set(:@use_url_path_for_native_authorization, true)
99
+ end
100
+
101
+ # TODO: maybe make it more generic for other flows too?
102
+ # Only allow one valid access token obtained via client credentials
103
+ # per client. If a new access token is obtained before the old one
104
+ # expired, the old one gets revoked (disabled by default)
105
+ def revoke_previous_client_credentials_token
106
+ @config.instance_variable_set(:@revoke_previous_client_credentials_token, true)
141
107
  end
142
108
 
143
109
  # Use an API mode for applications generated with --api argument
@@ -146,6 +112,12 @@ module Doorkeeper
146
112
  @config.instance_variable_set(:@api_only, true)
147
113
  end
148
114
 
115
+ # Enables polymorphic Resource Owner association for Access Grant and
116
+ # Access Token models. Requires additional database columns to be setup.
117
+ def use_polymorphic_resource_owner
118
+ @config.instance_variable_set(:@polymorphic_resource_owner, true)
119
+ end
120
+
149
121
  # Forbids creating/updating applications with arbitrary scopes that are
150
122
  # not in configuration, i.e. `default_scopes` or `optional_scopes`.
151
123
  # (disabled by default)
@@ -195,8 +167,7 @@ module Doorkeeper
195
167
  def configure_secrets_for(type, using:, fallback:)
196
168
  raise ArgumentError, "Invalid type #{type}" if %i[application token].exclude?(type)
197
169
 
198
- @config.instance_variable_set(:"@#{type}_secret_strategy",
199
- using.constantize)
170
+ @config.instance_variable_set(:"@#{type}_secret_strategy", using.constantize)
200
171
 
201
172
  if fallback.nil?
202
173
  return
@@ -204,18 +175,21 @@ module Doorkeeper
204
175
  fallback = "::Doorkeeper::SecretStoring::Plain"
205
176
  end
206
177
 
207
- @config.instance_variable_set(:"@#{type}_secret_fallback_strategy",
208
- fallback.constantize)
178
+ @config.instance_variable_set(:"@#{type}_secret_fallback_strategy", fallback.constantize)
209
179
  end
210
180
  end
211
181
 
182
+ # Replace with `default: Builder` when we drop support of Rails < 5.2
183
+ mattr_reader(:builder_class) { Builder }
184
+
212
185
  extend Option
186
+ include Validations
213
187
 
214
188
  option :resource_owner_authenticator,
215
189
  as: :authenticate_resource_owner,
216
190
  default: (lambda do |_routes|
217
191
  ::Rails.logger.warn(
218
- I18n.t("doorkeeper.errors.messages.resource_owner_authenticator_not_configured")
192
+ I18n.t("doorkeeper.errors.messages.resource_owner_authenticator_not_configured"),
219
193
  )
220
194
 
221
195
  nil
@@ -225,7 +199,7 @@ module Doorkeeper
225
199
  as: :authenticate_admin,
226
200
  default: (lambda do |_routes|
227
201
  ::Rails.logger.warn(
228
- I18n.t("doorkeeper.errors.messages.admin_authenticator_not_configured")
202
+ I18n.t("doorkeeper.errors.messages.admin_authenticator_not_configured"),
229
203
  )
230
204
 
231
205
  head :forbidden
@@ -234,15 +208,15 @@ module Doorkeeper
234
208
  option :resource_owner_from_credentials,
235
209
  default: (lambda do |_routes|
236
210
  ::Rails.logger.warn(
237
- I18n.t("doorkeeper.errors.messages.credential_flow_not_configured")
211
+ I18n.t("doorkeeper.errors.messages.credential_flow_not_configured"),
238
212
  )
239
213
 
240
214
  nil
241
215
  end)
242
216
 
243
217
  # Hooks for authorization
244
- option :before_successful_authorization, default: ->(_context) {}
245
- option :after_successful_authorization, default: ->(_context) {}
218
+ option :before_successful_authorization, default: ->(_controller, _context = nil) {}
219
+ option :after_successful_authorization, default: ->(_controller, _context = nil) {}
246
220
  # Hooks for strategies responses
247
221
  option :before_successful_strategy_response, default: ->(_request) {}
248
222
  option :after_successful_strategy_response, default: ->(_request, _response) {}
@@ -254,10 +228,61 @@ module Doorkeeper
254
228
  option :custom_access_token_expires_in, default: ->(_context) { nil }
255
229
  option :authorization_code_expires_in, default: 600
256
230
  option :orm, default: :active_record
257
- option :native_redirect_uri, default: "urn:ietf:wg:oauth:2.0:oob"
258
- option :active_record_options, default: {}
231
+ option :native_redirect_uri, default: "urn:ietf:wg:oauth:2.0:oob", deprecated: true
259
232
  option :grant_flows, default: %w[authorization_code client_credentials]
260
233
  option :handle_auth_errors, default: :render
234
+ option :token_lookup_batch_size, default: 10_000
235
+ # Sets the token_reuse_limit
236
+ # It will be used only when reuse_access_token option in enabled
237
+ # By default it will be 100
238
+ # It will be used for token reusablity to some threshold percentage
239
+ # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/1189
240
+ option :token_reuse_limit, default: 100
241
+
242
+ # Don't require client authentication for password grants. If client credentials
243
+ # are present they will still be validated, and the grant rejected if the credentials
244
+ # are invalid.
245
+ #
246
+ # This is discouraged. Spec says that password grants always require a client.
247
+ #
248
+ # See https://github.com/doorkeeper-gem/doorkeeper/issues/1412#issuecomment-632750422
249
+ # and https://github.com/doorkeeper-gem/doorkeeper/pull/1420
250
+ #
251
+ # Since many applications use this unsafe behavior in the wild, this is kept as a
252
+ # not-recommended option. You should be aware that you are not following the OAuth
253
+ # spec, and understand the security implications of doing so.
254
+ option :skip_client_authentication_for_password_grant,
255
+ default: false
256
+
257
+ # Hook to allow arbitrary user-client authorization
258
+ option :authorize_resource_owner_for_client,
259
+ default: ->(_client, _resource_owner) { true }
260
+
261
+ # Allows to customize OAuth grant flows that +each+ application support.
262
+ # You can configure a custom block (or use a class respond to `#call`) that must
263
+ # return `true` in case Application instance supports requested OAuth grant flow
264
+ # during the authorization request to the server. This configuration +doesn't+
265
+ # set flows per application, it only allows to check if application supports
266
+ # specific grant flow.
267
+ #
268
+ # For example you can add an additional database column to `oauth_applications` table,
269
+ # say `t.array :grant_flows, default: []`, and store allowed grant flows that can
270
+ # be used with this application there. Then when authorization requested Doorkeeper
271
+ # will call this block to check if specific Application (passed with client_id and/or
272
+ # client_secret) is allowed to perform the request for the specific grant type
273
+ # (authorization, password, client_credentials, etc).
274
+ #
275
+ # Example of the block:
276
+ #
277
+ # ->(flow, client) { client.grant_flows.include?(flow) }
278
+ #
279
+ # In case this option invocation result is `false`, Doorkeeper server returns
280
+ # :unauthorized_client error and stops the request.
281
+ #
282
+ # @param allow_grant_flow_for_client [Proc] Block or any object respond to #call
283
+ # @return [Boolean] `true` if allow or `false` if forbid the request
284
+ #
285
+ option :allow_grant_flow_for_client, default: ->(_grant_flow, _client) { true }
261
286
 
262
287
  # Allows to forbid specific Application redirect URI's by custom rules.
263
288
  # Doesn't forbid any URI by default.
@@ -288,7 +313,7 @@ module Doorkeeper
288
313
  option :force_ssl_in_redirect_uri, default: !Rails.env.development?
289
314
 
290
315
  # Use a custom class for generating the access token.
291
- # https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
316
+ # https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-access-token-generator
292
317
  #
293
318
  # @param access_token_generator [String]
294
319
  # the name of the access token generator class
@@ -296,21 +321,57 @@ module Doorkeeper
296
321
  option :access_token_generator,
297
322
  default: "Doorkeeper::OAuth::Helpers::UniqueToken"
298
323
 
324
+ # Allows additional data to be received when granting access to an Application, and for this
325
+ # additional data to be sent with subsequently generated access tokens. The access grant and
326
+ # access token models will both need to respond to the specified attribute names.
327
+ #
328
+ # @param attributes [Array] The array of custom attribute names to be saved
329
+ #
330
+ option :custom_access_token_attributes,
331
+ default: []
332
+
333
+ # Use a custom class for generating the application secret.
334
+ # https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-application-secret-generator
335
+ #
336
+ # @param application_secret_generator [String]
337
+ # the name of the application secret generator class
338
+ #
339
+ option :application_secret_generator,
340
+ default: "Doorkeeper::OAuth::Helpers::UniqueToken"
341
+
299
342
  # Default access token generator is a SecureRandom class from Ruby stdlib.
300
343
  # This option defines which method will be used to generate a unique token value.
301
344
  #
302
- # @param access_token_generator [String]
303
- # the name of the access token generator class
345
+ # @param default_generator_method [Symbol]
346
+ # the method name of the default access token generator
304
347
  #
305
348
  option :default_generator_method, default: :urlsafe_base64
306
349
 
307
350
  # The controller Doorkeeper::ApplicationController inherits from.
308
351
  # Defaults to ActionController::Base.
309
- # https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
352
+ # https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-controllers
310
353
  #
311
354
  # @param base_controller [String] the name of the base controller
312
355
  option :base_controller,
313
- default: "ActionController::Base"
356
+ default: (lambda do
357
+ api_only ? "ActionController::API" : "ActionController::Base"
358
+ end)
359
+
360
+ # The controller Doorkeeper::ApplicationMetalController inherits from.
361
+ # Defaults to ActionController::API.
362
+ #
363
+ # @param base_metal_controller [String] the name of the base controller
364
+ option :base_metal_controller,
365
+ default: "ActionController::API"
366
+
367
+ option :access_token_class,
368
+ default: "Doorkeeper::AccessToken"
369
+
370
+ option :access_grant_class,
371
+ default: "Doorkeeper::AccessGrant"
372
+
373
+ option :application_class,
374
+ default: "Doorkeeper::Application"
314
375
 
315
376
  # Allows to set blank redirect URIs for Applications in case
316
377
  # server configured to use URI-less grant flows.
@@ -321,17 +382,72 @@ module Doorkeeper
321
382
  grant_flows.exclude?("implicit")
322
383
  end)
323
384
 
324
- attr_reader :api_only,
325
- :enforce_content_type,
326
- :reuse_access_token,
385
+ # Configure protection of token introspection request.
386
+ # By default this configuration allows to introspect a token by
387
+ # another token of the same application, or to introspect the token
388
+ # that belongs to authorized client, or access token has been introspected
389
+ # is a public one (doesn't belong to any client)
390
+ #
391
+ # You can define any custom rule you need or just disable token
392
+ # introspection at all.
393
+ #
394
+ # @param token [Doorkeeper::AccessToken]
395
+ # token to be introspected
396
+ #
397
+ # @param authorized_client [Doorkeeper::Application]
398
+ # authorized client (if request is authorized using Basic auth with
399
+ # Client Credentials for example)
400
+ #
401
+ # @param authorized_token [Doorkeeper::AccessToken]
402
+ # Bearer token used to authorize the request
403
+ #
404
+ option :allow_token_introspection,
405
+ default: (lambda do |token, authorized_client, authorized_token|
406
+ if authorized_token
407
+ authorized_token.application == token&.application
408
+ elsif token.application
409
+ authorized_client == token.application
410
+ else
411
+ true
412
+ end
413
+ end)
414
+
415
+ attr_reader :reuse_access_token,
327
416
  :token_secret_fallback_strategy,
328
417
  :application_secret_fallback_strategy
329
418
 
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
419
+ def clear_cache!
420
+ %i[
421
+ application_model
422
+ access_token_model
423
+ access_grant_model
424
+ ].each do |var|
425
+ remove_instance_variable("@#{var}") if instance_variable_defined?("@#{var}")
426
+ end
427
+ end
428
+
429
+ # Doorkeeper Access Token model class.
430
+ #
431
+ # @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
432
+ #
433
+ def access_token_model
434
+ @access_token_model ||= access_token_class.constantize
435
+ end
436
+
437
+ # Doorkeeper Access Grant model class.
438
+ #
439
+ # @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
440
+ #
441
+ def access_grant_model
442
+ @access_grant_model ||= access_grant_class.constantize
443
+ end
444
+
445
+ # Doorkeeper Application model class.
446
+ #
447
+ # @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
448
+ #
449
+ def application_model
450
+ @application_model ||= application_class.constantize
335
451
  end
336
452
 
337
453
  def api_only
@@ -350,8 +466,19 @@ module Doorkeeper
350
466
  end
351
467
  end
352
468
 
353
- def token_reuse_limit
354
- @token_reuse_limit ||= 100
469
+ def resolve_controller(name)
470
+ config_option = public_send(:"#{name}_controller")
471
+ controller_name = if config_option.respond_to?(:call)
472
+ instance_exec(&config_option)
473
+ else
474
+ config_option
475
+ end
476
+
477
+ controller_name.constantize
478
+ end
479
+
480
+ def revoke_previous_client_credentials_token?
481
+ option_set? :revoke_previous_client_credentials_token
355
482
  end
356
483
 
357
484
  def enforce_configured_scopes?
@@ -362,6 +489,10 @@ module Doorkeeper
362
489
  option_set? :enable_application_owner
363
490
  end
364
491
 
492
+ def polymorphic_resource_owner?
493
+ option_set? :polymorphic_resource_owner
494
+ end
495
+
365
496
  def confirm_application_owner?
366
497
  option_set? :confirm_application_owner
367
498
  end
@@ -370,6 +501,10 @@ module Doorkeeper
370
501
  handle_auth_errors == :raise
371
502
  end
372
503
 
504
+ def application_secret_hashed?
505
+ instance_variable_defined?(:"@application_secret_strategy")
506
+ end
507
+
373
508
  def token_secret_strategy
374
509
  @token_secret_strategy ||= ::Doorkeeper::SecretStoring::Plain
375
510
  end
@@ -406,85 +541,114 @@ module Doorkeeper
406
541
  ]
407
542
  end
408
543
 
544
+ def enabled_grant_flows
545
+ @enabled_grant_flows ||= calculate_grant_flows.map { |name| Doorkeeper::GrantFlow.get(name) }.compact
546
+ end
547
+
548
+ def authorization_response_flows
549
+ @authorization_response_flows ||= enabled_grant_flows.select(&:handles_response_type?) +
550
+ deprecated_authorization_flows
551
+ end
552
+
553
+ def token_grant_flows
554
+ @token_grant_flows ||= calculate_token_grant_flows
555
+ end
556
+
409
557
  def authorization_response_types
410
- @authorization_response_types ||= calculate_authorization_response_types.freeze
558
+ authorization_response_flows.map(&:response_type_matches)
411
559
  end
412
560
 
413
561
  def token_grant_types
414
- @token_grant_types ||= calculate_token_grant_types.freeze
562
+ token_grant_flows.map(&:grant_type_matches)
415
563
  end
416
564
 
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
565
+ # [NOTE]: deprecated and will be removed soon
566
+ def deprecated_token_grant_types_resolver
567
+ @deprecated_token_grant_types ||= calculate_token_grant_types
423
568
  end
424
-
425
- def option_defined?(name)
426
- instance_variable_defined?("@#{name}")
569
+
570
+ def native_authorization_code_route
571
+ @use_url_path_for_native_authorization = false unless defined?(@use_url_path_for_native_authorization)
572
+ @use_url_path_for_native_authorization ? '/:code' : '/native'
427
573
  end
428
574
 
429
- private
575
+ # [NOTE]: deprecated and will be removed soon
576
+ def deprecated_authorization_flows
577
+ response_types = calculate_authorization_response_types
430
578
 
431
- # Helper to read boolearized configuration option
432
- def option_set?(instance_key)
433
- var = instance_variable_get("@#{instance_key}")
434
- !!(defined?(var) && var)
579
+ if response_types.any?
580
+ ::Kernel.warn <<~WARNING
581
+ Please, don't patch Doorkeeper::Config#calculate_authorization_response_types method.
582
+ Register your custom grant flows using the public API:
583
+ `Doorkeeper::GrantFlow.register(grant_flow_name, **options)`.
584
+ WARNING
585
+ end
586
+
587
+ response_types.map do |response_type|
588
+ Doorkeeper::GrantFlow::FallbackFlow.new(response_type, response_type_matches: response_type)
589
+ end
435
590
  end
436
591
 
437
- # Determines what values are acceptable for 'response_type' param in
438
- # authorization request endpoint, and return them as an array of strings.
439
- #
592
+ # [NOTE]: deprecated and will be removed soon
440
593
  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
594
+ []
445
595
  end
446
596
 
447
- # Determines what values are acceptable for 'grant_type' param token
448
- # request endpoint, and return them in array.
449
- #
597
+ # [NOTE]: deprecated and will be removed soon
450
598
  def calculate_token_grant_types
451
599
  types = grant_flows - ["implicit"]
452
600
  types << "refresh_token" if refresh_token_enabled?
453
601
  types
454
602
  end
455
603
 
456
- # Determine whether +reuse_access_token+ and a non-restorable
457
- # +token_secret_strategy+ have both been activated.
604
+ # Calculates grant flows configured by the user in Doorkeeper
605
+ # configuration considering registered aliases that is exposed
606
+ # to single or multiple other flows.
458
607
  #
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?
608
+ def calculate_grant_flows
609
+ configured_flows = grant_flows.map(&:to_s)
610
+ aliases = Doorkeeper::GrantFlow.aliases.keys.map(&:to_s)
611
+
612
+ flows = configured_flows - aliases
613
+ aliases.each do |flow_alias|
614
+ next unless configured_flows.include?(flow_alias)
615
+
616
+ flows.concat(Doorkeeper::GrantFlow.expand_alias(flow_alias))
617
+ end
618
+
619
+ flows.flatten.uniq
620
+ end
621
+
622
+ def allow_blank_redirect_uri?(application = nil)
623
+ if allow_blank_redirect_uri.respond_to?(:call)
624
+ allow_blank_redirect_uri.call(grant_flows, application)
625
+ else
626
+ allow_blank_redirect_uri
627
+ end
628
+ end
629
+
630
+ def allow_grant_flow_for_client?(grant_flow, client)
631
+ return true unless option_defined?(:allow_grant_flow_for_client)
463
632
 
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
633
+ allow_grant_flow_for_client.call(grant_flow, client)
470
634
  end
471
635
 
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
636
+ def option_defined?(name)
637
+ instance_variable_defined?("@#{name}")
477
638
  end
478
639
 
479
- def validate_token_reuse_limit
480
- return if !reuse_access_token ||
481
- (token_reuse_limit > 0 && token_reuse_limit <= 100)
640
+ private
641
+
642
+ # Helper to read boolearized configuration option
643
+ def option_set?(instance_key)
644
+ var = instance_variable_get("@#{instance_key}")
645
+ !!(defined?(var) && var)
646
+ end
482
647
 
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
648
+ def calculate_token_grant_flows
649
+ flows = enabled_grant_flows.select(&:handles_grant_type?)
650
+ flows << Doorkeeper::GrantFlow.get("refresh_token") if refresh_token_enabled?
651
+ flows
488
652
  end
489
653
  end
490
654
  end
@@ -2,9 +2,12 @@
2
2
 
3
3
  module Doorkeeper
4
4
  class Engine < Rails::Engine
5
- initializer "doorkeeper.params.filter" do |app|
6
- parameters = %w[client_secret code authentication_token access_token refresh_token]
7
- app.config.filter_parameters << /^(#{Regexp.union parameters})$/
5
+ initializer "doorkeeper.params.filter", after: :load_config_initializers do |app|
6
+ if Doorkeeper.configured?
7
+ parameters = %w[client_secret authentication_token access_token refresh_token]
8
+ parameters << "code" if Doorkeeper.config.grant_flows.include?("authorization_code")
9
+ app.config.filter_parameters << /^(#{Regexp.union(parameters)})$/
10
+ end
8
11
  end
9
12
 
10
13
  initializer "doorkeeper.routes" do
@@ -17,6 +20,10 @@ module Doorkeeper
17
20
  end
18
21
  end
19
22
 
23
+ config.to_prepare do
24
+ Doorkeeper.run_orm_hooks
25
+ end
26
+
20
27
  if defined?(Sprockets) && Sprockets::VERSION.chr.to_i >= 4
21
28
  initializer "doorkeeper.assets.precompile" do |app|
22
29
  # Force users to use:
@@ -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