doorkeeper 5.3.3 → 5.6.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +216 -9
- data/README.md +30 -21
- data/app/controllers/doorkeeper/application_controller.rb +1 -0
- data/app/controllers/doorkeeper/applications_controller.rb +4 -4
- data/app/controllers/doorkeeper/authorizations_controller.rb +66 -22
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +3 -3
- data/app/controllers/doorkeeper/token_info_controller.rb +12 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +73 -25
- data/app/helpers/doorkeeper/dashboard_helper.rb +1 -1
- data/app/views/doorkeeper/applications/_form.html.erb +1 -1
- data/app/views/doorkeeper/applications/show.html.erb +35 -14
- data/app/views/doorkeeper/authorizations/error.html.erb +3 -1
- data/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
- data/app/views/doorkeeper/authorizations/new.html.erb +16 -14
- data/config/locales/en.yml +9 -2
- data/lib/doorkeeper/config/abstract_builder.rb +28 -0
- data/lib/doorkeeper/config/option.rb +26 -14
- data/lib/doorkeeper/config/validations.rb +53 -0
- data/lib/doorkeeper/config.rb +182 -134
- data/lib/doorkeeper/engine.rb +10 -3
- data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
- data/lib/doorkeeper/grant_flow/flow.rb +44 -0
- data/lib/doorkeeper/grant_flow/registry.rb +50 -0
- data/lib/doorkeeper/grant_flow.rb +45 -0
- data/lib/doorkeeper/grape/helpers.rb +1 -1
- data/lib/doorkeeper/helpers/controller.rb +9 -5
- data/lib/doorkeeper/models/access_grant_mixin.rb +22 -19
- data/lib/doorkeeper/models/access_token_mixin.rb +115 -52
- data/lib/doorkeeper/models/application_mixin.rb +5 -4
- data/lib/doorkeeper/models/concerns/expirable.rb +1 -1
- data/lib/doorkeeper/models/concerns/expiration_time_sql_math.rb +88 -0
- data/lib/doorkeeper/models/concerns/polymorphic_resource_owner.rb +30 -0
- data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
- data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
- data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
- data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
- data/lib/doorkeeper/oauth/authorization/code.rb +25 -6
- data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
- data/lib/doorkeeper/oauth/authorization/token.rb +24 -16
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
- data/lib/doorkeeper/oauth/authorization_code_request.rb +34 -21
- data/lib/doorkeeper/oauth/base_request.rb +19 -26
- data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
- data/lib/doorkeeper/oauth/client.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +31 -15
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +4 -2
- data/lib/doorkeeper/oauth/client_credentials/validator.rb +5 -4
- data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
- data/lib/doorkeeper/oauth/code_request.rb +4 -4
- data/lib/doorkeeper/oauth/code_response.rb +22 -12
- data/lib/doorkeeper/oauth/error_response.rb +7 -9
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +2 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -8
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +2 -2
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +4 -22
- data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
- data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -2
- data/lib/doorkeeper/oauth/password_access_token_request.rb +26 -8
- data/lib/doorkeeper/oauth/pre_authorization.rb +65 -33
- data/lib/doorkeeper/oauth/refresh_token_request.rb +42 -25
- data/lib/doorkeeper/oauth/token.rb +5 -6
- data/lib/doorkeeper/oauth/token_introspection.rb +8 -12
- data/lib/doorkeeper/oauth/token_request.rb +3 -3
- data/lib/doorkeeper/oauth/token_response.rb +2 -3
- data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +14 -4
- data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +34 -4
- data/lib/doorkeeper/orm/active_record/mixins/application.rb +28 -5
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +6 -1
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +5 -2
- data/lib/doorkeeper/orm/active_record.rb +30 -38
- data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
- data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
- data/lib/doorkeeper/rails/routes/registry.rb +45 -0
- data/lib/doorkeeper/rails/routes.rb +25 -22
- data/lib/doorkeeper/rake/db.rake +3 -3
- data/lib/doorkeeper/request/password.rb +1 -0
- data/lib/doorkeeper/request/refresh_token.rb +2 -1
- data/lib/doorkeeper/request/strategy.rb +2 -2
- data/lib/doorkeeper/request.rb +49 -12
- data/lib/doorkeeper/server.rb +4 -4
- data/lib/doorkeeper/stale_records_cleaner.rb +4 -4
- data/lib/doorkeeper/version.rb +2 -6
- data/lib/doorkeeper.rb +181 -81
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
- data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
- data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +3 -1
- data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
- data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +73 -17
- data/lib/generators/doorkeeper/templates/migration.rb.erb +28 -9
- metadata +48 -316
- data/Appraisals +0 -40
- data/CODE_OF_CONDUCT.md +0 -46
- data/CONTRIBUTING.md +0 -49
- data/Dangerfile +0 -67
- data/Dockerfile +0 -29
- data/Gemfile +0 -25
- data/NEWS.md +0 -1
- data/RELEASING.md +0 -11
- data/Rakefile +0 -28
- data/SECURITY.md +0 -15
- data/UPGRADE.md +0 -2
- data/bin/console +0 -16
- data/doorkeeper.gemspec +0 -42
- data/gemfiles/rails_5_0.gemfile +0 -18
- data/gemfiles/rails_5_1.gemfile +0 -18
- data/gemfiles/rails_5_2.gemfile +0 -18
- data/gemfiles/rails_6_0.gemfile +0 -18
- data/gemfiles/rails_master.gemfile +0 -18
- data/spec/controllers/application_metal_controller_spec.rb +0 -64
- data/spec/controllers/applications_controller_spec.rb +0 -274
- data/spec/controllers/authorizations_controller_spec.rb +0 -608
- data/spec/controllers/protected_resources_controller_spec.rb +0 -361
- data/spec/controllers/token_info_controller_spec.rb +0 -50
- data/spec/controllers/tokens_controller_spec.rb +0 -498
- data/spec/dummy/Rakefile +0 -9
- data/spec/dummy/app/assets/config/manifest.js +0 -2
- data/spec/dummy/app/controllers/application_controller.rb +0 -5
- data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
- data/spec/dummy/app/controllers/home_controller.rb +0 -18
- data/spec/dummy/app/controllers/metal_controller.rb +0 -13
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
- data/spec/dummy/app/helpers/application_helper.rb +0 -7
- data/spec/dummy/app/models/user.rb +0 -7
- data/spec/dummy/app/views/home/index.html.erb +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/dummy/config/application.rb +0 -49
- data/spec/dummy/config/boot.rb +0 -7
- data/spec/dummy/config/database.yml +0 -15
- data/spec/dummy/config/environment.rb +0 -5
- data/spec/dummy/config/environments/development.rb +0 -31
- data/spec/dummy/config/environments/production.rb +0 -64
- data/spec/dummy/config/environments/test.rb +0 -45
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
- data/spec/dummy/config/initializers/doorkeeper.rb +0 -166
- data/spec/dummy/config/initializers/secret_token.rb +0 -10
- data/spec/dummy/config/initializers/session_store.rb +0 -10
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
- data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
- data/spec/dummy/config/routes.rb +0 -13
- data/spec/dummy/config.ru +0 -6
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
- data/spec/dummy/db/schema.rb +0 -68
- data/spec/dummy/public/404.html +0 -26
- data/spec/dummy/public/422.html +0 -26
- data/spec/dummy/public/500.html +0 -26
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +0 -9
- data/spec/factories.rb +0 -30
- data/spec/generators/application_owner_generator_spec.rb +0 -28
- data/spec/generators/confidential_applications_generator_spec.rb +0 -29
- data/spec/generators/install_generator_spec.rb +0 -36
- data/spec/generators/migration_generator_spec.rb +0 -28
- data/spec/generators/pkce_generator_spec.rb +0 -28
- data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
- data/spec/generators/templates/routes.rb +0 -4
- data/spec/generators/views_generator_spec.rb +0 -29
- data/spec/grape/grape_integration_spec.rb +0 -137
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
- data/spec/lib/config_spec.rb +0 -809
- data/spec/lib/doorkeeper_spec.rb +0 -27
- data/spec/lib/models/expirable_spec.rb +0 -61
- data/spec/lib/models/reusable_spec.rb +0 -40
- data/spec/lib/models/revocable_spec.rb +0 -59
- data/spec/lib/models/scopes_spec.rb +0 -53
- data/spec/lib/models/secret_storable_spec.rb +0 -135
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
- data/spec/lib/oauth/authorization_code_request_spec.rb +0 -170
- data/spec/lib/oauth/base_request_spec.rb +0 -224
- data/spec/lib/oauth/base_response_spec.rb +0 -45
- data/spec/lib/oauth/client/credentials_spec.rb +0 -90
- data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -134
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
- data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
- data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
- data/spec/lib/oauth/client_credentials_request_spec.rb +0 -107
- data/spec/lib/oauth/client_spec.rb +0 -38
- data/spec/lib/oauth/code_request_spec.rb +0 -46
- data/spec/lib/oauth/code_response_spec.rb +0 -32
- data/spec/lib/oauth/error_response_spec.rb +0 -64
- data/spec/lib/oauth/error_spec.rb +0 -21
- data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -20
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -110
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -262
- data/spec/lib/oauth/invalid_request_response_spec.rb +0 -73
- data/spec/lib/oauth/invalid_token_response_spec.rb +0 -53
- data/spec/lib/oauth/password_access_token_request_spec.rb +0 -190
- data/spec/lib/oauth/pre_authorization_spec.rb +0 -223
- data/spec/lib/oauth/refresh_token_request_spec.rb +0 -177
- data/spec/lib/oauth/scopes_spec.rb +0 -146
- data/spec/lib/oauth/token_request_spec.rb +0 -157
- data/spec/lib/oauth/token_response_spec.rb +0 -84
- data/spec/lib/oauth/token_spec.rb +0 -156
- data/spec/lib/request/strategy_spec.rb +0 -54
- data/spec/lib/secret_storing/base_spec.rb +0 -60
- data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
- data/spec/lib/secret_storing/plain_spec.rb +0 -44
- data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
- data/spec/lib/server_spec.rb +0 -49
- data/spec/lib/stale_records_cleaner_spec.rb +0 -89
- data/spec/models/doorkeeper/access_grant_spec.rb +0 -161
- data/spec/models/doorkeeper/access_token_spec.rb +0 -622
- data/spec/models/doorkeeper/application_spec.rb +0 -482
- data/spec/requests/applications/applications_request_spec.rb +0 -259
- data/spec/requests/applications/authorized_applications_spec.rb +0 -32
- data/spec/requests/endpoints/authorization_spec.rb +0 -91
- data/spec/requests/endpoints/token_spec.rb +0 -75
- data/spec/requests/flows/authorization_code_errors_spec.rb +0 -79
- data/spec/requests/flows/authorization_code_spec.rb +0 -525
- data/spec/requests/flows/client_credentials_spec.rb +0 -166
- data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -46
- data/spec/requests/flows/implicit_grant_spec.rb +0 -91
- data/spec/requests/flows/password_spec.rb +0 -316
- data/spec/requests/flows/refresh_token_spec.rb +0 -233
- data/spec/requests/flows/revoke_token_spec.rb +0 -157
- data/spec/requests/flows/skip_authorization_spec.rb +0 -66
- data/spec/requests/protected_resources/metal_spec.rb +0 -16
- data/spec/requests/protected_resources/private_api_spec.rb +0 -83
- data/spec/routing/custom_controller_routes_spec.rb +0 -133
- data/spec/routing/default_routes_spec.rb +0 -41
- data/spec/routing/scoped_routes_spec.rb +0 -47
- data/spec/spec_helper.rb +0 -54
- data/spec/spec_helper_integration.rb +0 -4
- data/spec/support/dependencies/factory_bot.rb +0 -4
- data/spec/support/doorkeeper_rspec.rb +0 -22
- data/spec/support/helpers/access_token_request_helper.rb +0 -13
- data/spec/support/helpers/authorization_request_helper.rb +0 -43
- data/spec/support/helpers/config_helper.rb +0 -11
- data/spec/support/helpers/model_helper.rb +0 -78
- data/spec/support/helpers/request_spec_helper.rb +0 -110
- data/spec/support/helpers/url_helper.rb +0 -62
- data/spec/support/orm/active_record.rb +0 -5
- data/spec/support/shared/controllers_shared_context.rb +0 -133
- data/spec/support/shared/hashing_shared_context.rb +0 -36
- data/spec/support/shared/models_shared_examples.rb +0 -54
- data/spec/validators/redirect_uri_validator_spec.rb +0 -183
- data/spec/version/version_spec.rb +0 -17
data/lib/doorkeeper/config.rb
CHANGED
@@ -1,64 +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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
class << self
|
15
|
-
def configure(&block)
|
16
|
-
@config = Config::Builder.new(&block).build
|
17
|
-
setup_orm_adapter
|
18
|
-
setup_orm_models
|
19
|
-
setup_application_owner if @config.enable_application_owner?
|
20
|
-
@config
|
21
|
-
end
|
22
|
-
|
23
|
-
def configuration
|
24
|
-
@config || (raise MissingConfiguration)
|
25
|
-
end
|
26
|
-
|
27
|
-
alias config configuration
|
28
|
-
|
29
|
-
def setup_orm_adapter
|
30
|
-
@orm_adapter = "doorkeeper/orm/#{configuration.orm}".classify.constantize
|
31
|
-
rescue NameError => e
|
32
|
-
raise e, "ORM adapter not found (#{configuration.orm})", <<-ERROR_MSG.strip_heredoc
|
33
|
-
[doorkeeper] ORM adapter not found (#{configuration.orm}), or there was an error
|
34
|
-
trying to load it.
|
35
|
-
|
36
|
-
You probably need to add the related gem for this adapter to work with
|
37
|
-
doorkeeper.
|
38
|
-
ERROR_MSG
|
39
|
-
end
|
40
|
-
|
41
|
-
def setup_orm_models
|
42
|
-
@orm_adapter.initialize_models!
|
43
|
-
end
|
44
|
-
|
45
|
-
def setup_application_owner
|
46
|
-
@orm_adapter.initialize_application_owner!
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
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
|
+
#
|
50
13
|
class Config
|
51
|
-
|
52
|
-
|
53
|
-
@config = Config.new
|
54
|
-
instance_eval(&block)
|
55
|
-
end
|
56
|
-
|
57
|
-
def build
|
58
|
-
@config.validate
|
59
|
-
@config
|
60
|
-
end
|
61
|
-
|
14
|
+
# Default Doorkeeper configuration builder
|
15
|
+
class Builder < AbstractBuilder
|
62
16
|
# Provide support for an owner to be assigned to each registered
|
63
17
|
# application (disabled by default)
|
64
18
|
# Optional parameter confirmation: true (default false) if you want
|
@@ -135,13 +89,13 @@ module Doorkeeper
|
|
135
89
|
@config.instance_variable_set(:@reuse_access_token, true)
|
136
90
|
end
|
137
91
|
|
138
|
-
#
|
139
|
-
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/
|
143
|
-
def
|
144
|
-
@config.instance_variable_set(:@
|
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)
|
145
99
|
end
|
146
100
|
|
147
101
|
# TODO: maybe make it more generic for other flows too?
|
@@ -158,6 +112,12 @@ module Doorkeeper
|
|
158
112
|
@config.instance_variable_set(:@api_only, true)
|
159
113
|
end
|
160
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
|
+
|
161
121
|
# Forbids creating/updating applications with arbitrary scopes that are
|
162
122
|
# not in configuration, i.e. `default_scopes` or `optional_scopes`.
|
163
123
|
# (disabled by default)
|
@@ -219,7 +179,11 @@ module Doorkeeper
|
|
219
179
|
end
|
220
180
|
end
|
221
181
|
|
182
|
+
# Replace with `default: Builder` when we drop support of Rails < 5.2
|
183
|
+
mattr_reader(:builder_class) { Builder }
|
184
|
+
|
222
185
|
extend Option
|
186
|
+
include Validations
|
223
187
|
|
224
188
|
option :resource_owner_authenticator,
|
225
189
|
as: :authenticate_resource_owner,
|
@@ -251,8 +215,8 @@ module Doorkeeper
|
|
251
215
|
end)
|
252
216
|
|
253
217
|
# Hooks for authorization
|
254
|
-
option :before_successful_authorization, default: ->(_context) {}
|
255
|
-
option :after_successful_authorization, default: ->(_context) {}
|
218
|
+
option :before_successful_authorization, default: ->(_controller, _context = nil) {}
|
219
|
+
option :after_successful_authorization, default: ->(_controller, _context = nil) {}
|
256
220
|
# Hooks for strategies responses
|
257
221
|
option :before_successful_strategy_response, default: ->(_request) {}
|
258
222
|
option :after_successful_strategy_response, default: ->(_request, _response) {}
|
@@ -265,10 +229,34 @@ module Doorkeeper
|
|
265
229
|
option :authorization_code_expires_in, default: 600
|
266
230
|
option :orm, default: :active_record
|
267
231
|
option :native_redirect_uri, default: "urn:ietf:wg:oauth:2.0:oob", deprecated: true
|
268
|
-
option :active_record_options, default: {}
|
269
232
|
option :grant_flows, default: %w[authorization_code client_credentials]
|
270
233
|
option :handle_auth_errors, default: :render
|
271
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 }
|
272
260
|
|
273
261
|
# Allows to customize OAuth grant flows that +each+ application support.
|
274
262
|
# You can configure a custom block (or use a class respond to `#call`) that must
|
@@ -333,17 +321,35 @@ module Doorkeeper
|
|
333
321
|
option :access_token_generator,
|
334
322
|
default: "Doorkeeper::OAuth::Helpers::UniqueToken"
|
335
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
|
+
|
336
342
|
# Default access token generator is a SecureRandom class from Ruby stdlib.
|
337
343
|
# This option defines which method will be used to generate a unique token value.
|
338
344
|
#
|
339
|
-
# @param
|
340
|
-
# the name of the access token generator
|
345
|
+
# @param default_generator_method [Symbol]
|
346
|
+
# the method name of the default access token generator
|
341
347
|
#
|
342
348
|
option :default_generator_method, default: :urlsafe_base64
|
343
349
|
|
344
350
|
# The controller Doorkeeper::ApplicationController inherits from.
|
345
351
|
# Defaults to ActionController::Base.
|
346
|
-
# https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-
|
352
|
+
# https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-controllers
|
347
353
|
#
|
348
354
|
# @param base_controller [String] the name of the base controller
|
349
355
|
option :base_controller,
|
@@ -410,21 +416,36 @@ module Doorkeeper
|
|
410
416
|
:token_secret_fallback_strategy,
|
411
417
|
:application_secret_fallback_strategy
|
412
418
|
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
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
|
418
427
|
end
|
419
428
|
|
429
|
+
# Doorkeeper Access Token model class.
|
430
|
+
#
|
431
|
+
# @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
|
432
|
+
#
|
420
433
|
def access_token_model
|
421
434
|
@access_token_model ||= access_token_class.constantize
|
422
435
|
end
|
423
436
|
|
437
|
+
# Doorkeeper Access Grant model class.
|
438
|
+
#
|
439
|
+
# @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
|
440
|
+
#
|
424
441
|
def access_grant_model
|
425
442
|
@access_grant_model ||= access_grant_class.constantize
|
426
443
|
end
|
427
444
|
|
445
|
+
# Doorkeeper Application model class.
|
446
|
+
#
|
447
|
+
# @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
|
448
|
+
#
|
428
449
|
def application_model
|
429
450
|
@application_model ||= application_class.constantize
|
430
451
|
end
|
@@ -445,14 +466,6 @@ module Doorkeeper
|
|
445
466
|
end
|
446
467
|
end
|
447
468
|
|
448
|
-
def token_reuse_limit
|
449
|
-
@token_reuse_limit ||= 100
|
450
|
-
end
|
451
|
-
|
452
|
-
def revoke_previous_client_credentials_token
|
453
|
-
@revoke_previous_client_credentials_token || false
|
454
|
-
end
|
455
|
-
|
456
469
|
def resolve_controller(name)
|
457
470
|
config_option = public_send(:"#{name}_controller")
|
458
471
|
controller_name = if config_option.respond_to?(:call)
|
@@ -464,6 +477,10 @@ module Doorkeeper
|
|
464
477
|
controller_name.constantize
|
465
478
|
end
|
466
479
|
|
480
|
+
def revoke_previous_client_credentials_token?
|
481
|
+
option_set? :revoke_previous_client_credentials_token
|
482
|
+
end
|
483
|
+
|
467
484
|
def enforce_configured_scopes?
|
468
485
|
option_set? :enforce_configured_scopes
|
469
486
|
end
|
@@ -472,6 +489,10 @@ module Doorkeeper
|
|
472
489
|
option_set? :enable_application_owner
|
473
490
|
end
|
474
491
|
|
492
|
+
def polymorphic_resource_owner?
|
493
|
+
option_set? :polymorphic_resource_owner
|
494
|
+
end
|
495
|
+
|
475
496
|
def confirm_application_owner?
|
476
497
|
option_set? :confirm_application_owner
|
477
498
|
end
|
@@ -480,6 +501,10 @@ module Doorkeeper
|
|
480
501
|
handle_auth_errors == :raise
|
481
502
|
end
|
482
503
|
|
504
|
+
def application_secret_hashed?
|
505
|
+
instance_variable_defined?(:"@application_secret_strategy")
|
506
|
+
end
|
507
|
+
|
483
508
|
def token_secret_strategy
|
484
509
|
@token_secret_strategy ||= ::Doorkeeper::SecretStoring::Plain
|
485
510
|
end
|
@@ -516,12 +541,82 @@ module Doorkeeper
|
|
516
541
|
]
|
517
542
|
end
|
518
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
|
+
|
519
557
|
def authorization_response_types
|
520
|
-
|
558
|
+
authorization_response_flows.map(&:response_type_matches)
|
521
559
|
end
|
522
560
|
|
523
561
|
def token_grant_types
|
524
|
-
|
562
|
+
token_grant_flows.map(&:grant_type_matches)
|
563
|
+
end
|
564
|
+
|
565
|
+
# [NOTE]: deprecated and will be removed soon
|
566
|
+
def deprecated_token_grant_types_resolver
|
567
|
+
@deprecated_token_grant_types ||= calculate_token_grant_types
|
568
|
+
end
|
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'
|
573
|
+
end
|
574
|
+
|
575
|
+
# [NOTE]: deprecated and will be removed soon
|
576
|
+
def deprecated_authorization_flows
|
577
|
+
response_types = calculate_authorization_response_types
|
578
|
+
|
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
|
590
|
+
end
|
591
|
+
|
592
|
+
# [NOTE]: deprecated and will be removed soon
|
593
|
+
def calculate_authorization_response_types
|
594
|
+
[]
|
595
|
+
end
|
596
|
+
|
597
|
+
# [NOTE]: deprecated and will be removed soon
|
598
|
+
def calculate_token_grant_types
|
599
|
+
types = grant_flows - ["implicit"]
|
600
|
+
types << "refresh_token" if refresh_token_enabled?
|
601
|
+
types
|
602
|
+
end
|
603
|
+
|
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.
|
607
|
+
#
|
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
|
525
620
|
end
|
526
621
|
|
527
622
|
def allow_blank_redirect_uri?(application = nil)
|
@@ -550,57 +645,10 @@ module Doorkeeper
|
|
550
645
|
!!(defined?(var) && var)
|
551
646
|
end
|
552
647
|
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
types = []
|
558
|
-
types << "code" if grant_flows.include? "authorization_code"
|
559
|
-
types << "token" if grant_flows.include? "implicit"
|
560
|
-
types
|
561
|
-
end
|
562
|
-
|
563
|
-
# Determines what values are acceptable for 'grant_type' param token
|
564
|
-
# request endpoint, and return them in array.
|
565
|
-
#
|
566
|
-
def calculate_token_grant_types
|
567
|
-
types = grant_flows - ["implicit"]
|
568
|
-
types << "refresh_token" if refresh_token_enabled?
|
569
|
-
types
|
570
|
-
end
|
571
|
-
|
572
|
-
# Determine whether +reuse_access_token+ and a non-restorable
|
573
|
-
# +token_secret_strategy+ have both been activated.
|
574
|
-
#
|
575
|
-
# In that case, disable reuse_access_token value and warn the user.
|
576
|
-
def validate_reuse_access_token_value
|
577
|
-
strategy = token_secret_strategy
|
578
|
-
return if !reuse_access_token || strategy.allows_restoring_secrets?
|
579
|
-
|
580
|
-
::Rails.logger.warn(
|
581
|
-
"You have configured both reuse_access_token " \
|
582
|
-
"AND strategy strategy '#{strategy}' that cannot restore tokens. " \
|
583
|
-
"This combination is unsupported. reuse_access_token will be disabled",
|
584
|
-
)
|
585
|
-
@reuse_access_token = false
|
586
|
-
end
|
587
|
-
|
588
|
-
# Validate that the provided strategies are valid for
|
589
|
-
# tokens and applications
|
590
|
-
def validate_secret_strategies
|
591
|
-
token_secret_strategy.validate_for :token
|
592
|
-
application_secret_strategy.validate_for :application
|
593
|
-
end
|
594
|
-
|
595
|
-
def validate_token_reuse_limit
|
596
|
-
return if !reuse_access_token ||
|
597
|
-
(token_reuse_limit > 0 && token_reuse_limit <= 100)
|
598
|
-
|
599
|
-
::Rails.logger.warn(
|
600
|
-
"You have configured an invalid value for token_reuse_limit option. " \
|
601
|
-
"It will be set to default 100",
|
602
|
-
)
|
603
|
-
@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
|
604
652
|
end
|
605
653
|
end
|
606
654
|
end
|
data/lib/doorkeeper/engine.rb
CHANGED
@@ -2,9 +2,12 @@
|
|
2
2
|
|
3
3
|
module Doorkeeper
|
4
4
|
class Engine < Rails::Engine
|
5
|
-
initializer "doorkeeper.params.filter" do |app|
|
6
|
-
|
7
|
-
|
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:
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper
|
4
|
+
module GrantFlow
|
5
|
+
class Flow
|
6
|
+
attr_reader :name, :grant_type_matches, :grant_type_strategy,
|
7
|
+
:response_type_matches, :response_type_strategy,
|
8
|
+
:response_mode_matches
|
9
|
+
|
10
|
+
def initialize(name, **options)
|
11
|
+
@name = name
|
12
|
+
@grant_type_matches = options[:grant_type_matches]
|
13
|
+
@grant_type_strategy = options[:grant_type_strategy]
|
14
|
+
@response_type_matches = options[:response_type_matches]
|
15
|
+
@response_type_strategy = options[:response_type_strategy]
|
16
|
+
@response_mode_matches = options[:response_mode_matches]
|
17
|
+
end
|
18
|
+
|
19
|
+
def handles_grant_type?
|
20
|
+
grant_type_matches.present?
|
21
|
+
end
|
22
|
+
|
23
|
+
def handles_response_type?
|
24
|
+
response_type_matches.present?
|
25
|
+
end
|
26
|
+
|
27
|
+
def matches_grant_type?(value)
|
28
|
+
grant_type_matches === value
|
29
|
+
end
|
30
|
+
|
31
|
+
def matches_response_type?(value)
|
32
|
+
response_type_matches === value
|
33
|
+
end
|
34
|
+
|
35
|
+
def default_response_mode
|
36
|
+
response_mode_matches[0]
|
37
|
+
end
|
38
|
+
|
39
|
+
def matches_response_mode?(value)
|
40
|
+
response_mode_matches.include?(value)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper
|
4
|
+
module GrantFlow
|
5
|
+
module Registry
|
6
|
+
mattr_accessor :flows
|
7
|
+
self.flows = {}
|
8
|
+
|
9
|
+
mattr_accessor :aliases
|
10
|
+
self.aliases = {}
|
11
|
+
|
12
|
+
# Allows to register custom OAuth grant flow so that Doorkeeper
|
13
|
+
# could recognize and process it.
|
14
|
+
#
|
15
|
+
def register(name_or_flow, **options)
|
16
|
+
unless name_or_flow.is_a?(Doorkeeper::GrantFlow::Flow)
|
17
|
+
name_or_flow = Flow.new(name_or_flow, **options)
|
18
|
+
end
|
19
|
+
|
20
|
+
flow_key = name_or_flow.name.to_sym
|
21
|
+
|
22
|
+
if flows.key?(flow_key)
|
23
|
+
::Kernel.warn <<~WARNING
|
24
|
+
[DOORKEEPER] '#{flow_key}' grant flow already registered and will be overridden
|
25
|
+
in #{caller(1..1).first}
|
26
|
+
WARNING
|
27
|
+
end
|
28
|
+
|
29
|
+
flows[flow_key] = name_or_flow
|
30
|
+
end
|
31
|
+
|
32
|
+
# Allows to register aliases that could be used in `grant_flows`
|
33
|
+
# configuration option. It is possible to have aliases like 1:1 or
|
34
|
+
# 1:N, i.e. "implicit_oidc" => ['token', 'id_token', 'id_token token'].
|
35
|
+
#
|
36
|
+
def register_alias(alias_name, **options)
|
37
|
+
aliases[alias_name.to_sym] = Array.wrap(options.fetch(:as))
|
38
|
+
end
|
39
|
+
|
40
|
+
def expand_alias(alias_name)
|
41
|
+
aliases.fetch(alias_name.to_sym, [])
|
42
|
+
end
|
43
|
+
|
44
|
+
# [NOTE]: make it to use #fetch after removing fallbacks
|
45
|
+
def get(name)
|
46
|
+
flows[name.to_sym]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "doorkeeper/grant_flow/flow"
|
4
|
+
require "doorkeeper/grant_flow/fallback_flow"
|
5
|
+
require "doorkeeper/grant_flow/registry"
|
6
|
+
|
7
|
+
module Doorkeeper
|
8
|
+
module GrantFlow
|
9
|
+
extend Registry
|
10
|
+
|
11
|
+
register(
|
12
|
+
:implicit,
|
13
|
+
response_type_matches: "token",
|
14
|
+
response_mode_matches: %w[fragment form_post],
|
15
|
+
response_type_strategy: Doorkeeper::Request::Token,
|
16
|
+
)
|
17
|
+
|
18
|
+
register(
|
19
|
+
:authorization_code,
|
20
|
+
response_type_matches: "code",
|
21
|
+
response_mode_matches: %w[query fragment form_post],
|
22
|
+
response_type_strategy: Doorkeeper::Request::Code,
|
23
|
+
grant_type_matches: "authorization_code",
|
24
|
+
grant_type_strategy: Doorkeeper::Request::AuthorizationCode,
|
25
|
+
)
|
26
|
+
|
27
|
+
register(
|
28
|
+
:client_credentials,
|
29
|
+
grant_type_matches: "client_credentials",
|
30
|
+
grant_type_strategy: Doorkeeper::Request::ClientCredentials,
|
31
|
+
)
|
32
|
+
|
33
|
+
register(
|
34
|
+
:password,
|
35
|
+
grant_type_matches: "password",
|
36
|
+
grant_type_strategy: Doorkeeper::Request::Password,
|
37
|
+
)
|
38
|
+
|
39
|
+
register(
|
40
|
+
:refresh_token,
|
41
|
+
grant_type_matches: "refresh_token",
|
42
|
+
grant_type_strategy: Doorkeeper::Request::RefreshToken,
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
@@ -16,6 +16,8 @@ module Doorkeeper
|
|
16
16
|
|
17
17
|
# :doc:
|
18
18
|
def current_resource_owner
|
19
|
+
return @current_resource_owner if defined?(@current_resource_owner)
|
20
|
+
|
19
21
|
@current_resource_owner ||= begin
|
20
22
|
instance_eval(&Doorkeeper.config.authenticate_resource_owner)
|
21
23
|
end
|
@@ -36,7 +38,9 @@ module Doorkeeper
|
|
36
38
|
|
37
39
|
# :doc:
|
38
40
|
def doorkeeper_token
|
39
|
-
@doorkeeper_token
|
41
|
+
return @doorkeeper_token if defined?(@doorkeeper_token)
|
42
|
+
|
43
|
+
@doorkeeper_token ||= OAuth::Token.authenticate(request, *config_methods)
|
40
44
|
end
|
41
45
|
|
42
46
|
def config_methods
|
@@ -58,10 +62,10 @@ module Doorkeeper
|
|
58
62
|
end
|
59
63
|
|
60
64
|
def handle_token_exception(exception)
|
61
|
-
error = get_error_response_from_exception
|
62
|
-
headers.merge!
|
65
|
+
error = get_error_response_from_exception(exception)
|
66
|
+
headers.merge!(error.headers)
|
63
67
|
self.response_body = error.body.to_json
|
64
|
-
self.status
|
68
|
+
self.status = error.status
|
65
69
|
end
|
66
70
|
|
67
71
|
def skip_authorization?
|
@@ -78,7 +82,7 @@ module Doorkeeper
|
|
78
82
|
end
|
79
83
|
|
80
84
|
def x_www_form_urlencoded?
|
81
|
-
request.
|
85
|
+
request.media_type == "application/x-www-form-urlencoded"
|
82
86
|
end
|
83
87
|
end
|
84
88
|
end
|