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.
- checksums.yaml +4 -4
- data/{NEWS.md → CHANGELOG.md} +242 -25
- data/README.md +21 -11
- data/app/controllers/doorkeeper/application_controller.rb +3 -2
- data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
- data/app/controllers/doorkeeper/applications_controller.rb +8 -7
- data/app/controllers/doorkeeper/authorizations_controller.rb +56 -19
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +6 -6
- data/app/controllers/doorkeeper/token_info_controller.rb +12 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +93 -25
- data/app/views/doorkeeper/applications/_form.html.erb +1 -7
- data/app/views/doorkeeper/applications/show.html.erb +35 -14
- data/app/views/doorkeeper/authorizations/form_post.html.erb +11 -0
- data/config/locales/en.yml +13 -3
- data/lib/doorkeeper/config/abstract_builder.rb +28 -0
- data/lib/doorkeeper/config/option.rb +20 -2
- data/lib/doorkeeper/config/validations.rb +53 -0
- data/lib/doorkeeper/config.rb +295 -121
- data/lib/doorkeeper/engine.rb +1 -1
- data/lib/doorkeeper/errors.rb +13 -18
- 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 +7 -3
- data/lib/doorkeeper/helpers/controller.rb +36 -11
- data/lib/doorkeeper/models/access_grant_mixin.rb +22 -18
- data/lib/doorkeeper/models/access_token_mixin.rb +194 -51
- data/lib/doorkeeper/models/application_mixin.rb +8 -7
- data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
- data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
- data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
- data/lib/doorkeeper/models/concerns/revocable.rb +1 -28
- 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 -14
- data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
- data/lib/doorkeeper/oauth/authorization/token.rb +24 -19
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
- data/lib/doorkeeper/oauth/authorization_code_request.rb +40 -21
- data/lib/doorkeeper/oauth/base_request.rb +21 -23
- data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
- data/lib/doorkeeper/oauth/client.rb +8 -9
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +45 -5
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +10 -8
- data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +13 -3
- data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
- data/lib/doorkeeper/oauth/code_request.rb +6 -12
- data/lib/doorkeeper/oauth/code_response.rb +24 -14
- data/lib/doorkeeper/oauth/error.rb +1 -1
- data/lib/doorkeeper/oauth/error_response.rb +10 -11
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +8 -12
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +8 -5
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +19 -5
- data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
- data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
- data/lib/doorkeeper/oauth/invalid_token_response.rb +7 -4
- data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +34 -11
- data/lib/doorkeeper/oauth/pre_authorization.rb +111 -42
- data/lib/doorkeeper/oauth/refresh_token_request.rb +45 -33
- data/lib/doorkeeper/oauth/token.rb +6 -7
- data/lib/doorkeeper/oauth/token_introspection.rb +24 -18
- data/lib/doorkeeper/oauth/token_request.rb +6 -20
- data/lib/doorkeeper/oauth/token_response.rb +1 -1
- data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
- data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
- data/lib/doorkeeper/orm/active_record/application.rb +5 -83
- data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +68 -0
- data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +59 -0
- data/lib/doorkeeper/orm/active_record/mixins/application.rb +198 -0
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
- data/lib/doorkeeper/orm/active_record.rb +20 -6
- data/lib/doorkeeper/rails/helpers.rb +4 -4
- 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 +17 -25
- data/lib/doorkeeper/rake/db.rake +6 -6
- data/lib/doorkeeper/rake/setup.rake +5 -0
- data/lib/doorkeeper/request/authorization_code.rb +5 -3
- data/lib/doorkeeper/request/client_credentials.rb +2 -2
- data/lib/doorkeeper/request/password.rb +3 -2
- data/lib/doorkeeper/request/refresh_token.rb +5 -4
- data/lib/doorkeeper/request/strategy.rb +2 -2
- data/lib/doorkeeper/request.rb +49 -17
- data/lib/doorkeeper/server.rb +7 -11
- data/lib/doorkeeper/stale_records_cleaner.rb +6 -2
- data/lib/doorkeeper/version.rb +2 -6
- data/lib/doorkeeper.rb +114 -79
- data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +2 -2
- data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
- data/lib/generators/doorkeeper/migration_generator.rb +1 -1
- data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +7 -7
- 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 +205 -43
- data/lib/generators/doorkeeper/templates/migration.rb.erb +18 -6
- metadata +45 -312
- data/.coveralls.yml +0 -1
- data/.github/ISSUE_TEMPLATE.md +0 -25
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
- data/.gitignore +0 -20
- data/.gitlab-ci.yml +0 -16
- data/.hound.yml +0 -3
- data/.rspec +0 -1
- data/.rubocop.yml +0 -50
- data/.travis.yml +0 -35
- data/Appraisals +0 -40
- data/CODE_OF_CONDUCT.md +0 -46
- data/CONTRIBUTING.md +0 -47
- data/Dangerfile +0 -67
- data/Gemfile +0 -24
- data/RELEASING.md +0 -10
- data/Rakefile +0 -28
- data/SECURITY.md +0 -15
- data/UPGRADE.md +0 -2
- data/app/validators/redirect_uri_validator.rb +0 -50
- data/bin/console +0 -16
- data/doorkeeper.gemspec +0 -34
- data/gemfiles/rails_5_0.gemfile +0 -17
- data/gemfiles/rails_5_1.gemfile +0 -17
- data/gemfiles/rails_5_2.gemfile +0 -17
- data/gemfiles/rails_6_0.gemfile +0 -17
- data/gemfiles/rails_master.gemfile +0 -17
- data/spec/controllers/application_metal_controller_spec.rb +0 -64
- data/spec/controllers/applications_controller_spec.rb +0 -180
- data/spec/controllers/authorizations_controller_spec.rb +0 -527
- data/spec/controllers/protected_resources_controller_spec.rb +0 -353
- data/spec/controllers/token_info_controller_spec.rb +0 -50
- data/spec/controllers/tokens_controller_spec.rb +0 -330
- 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 -47
- 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 -121
- 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 -697
- 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 -156
- data/spec/lib/oauth/base_request_spec.rb +0 -205
- data/spec/lib/oauth/base_response_spec.rb +0 -47
- data/spec/lib/oauth/client/credentials_spec.rb +0 -90
- data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -94
- 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 -29
- data/spec/lib/oauth/client_credentials_request_spec.rb +0 -109
- data/spec/lib/oauth/client_spec.rb +0 -38
- data/spec/lib/oauth/code_request_spec.rb +0 -47
- data/spec/lib/oauth/code_response_spec.rb +0 -36
- data/spec/lib/oauth/error_response_spec.rb +0 -66
- data/spec/lib/oauth/error_spec.rb +0 -23
- data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -22
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -98
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -247
- data/spec/lib/oauth/invalid_token_response_spec.rb +0 -55
- data/spec/lib/oauth/password_access_token_request_spec.rb +0 -192
- data/spec/lib/oauth/pre_authorization_spec.rb +0 -215
- data/spec/lib/oauth/refresh_token_request_spec.rb +0 -177
- data/spec/lib/oauth/scopes_spec.rb +0 -148
- data/spec/lib/oauth/token_request_spec.rb +0 -150
- data/spec/lib/oauth/token_response_spec.rb +0 -86
- data/spec/lib/oauth/token_spec.rb +0 -158
- 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 -61
- data/spec/lib/stale_records_cleaner_spec.rb +0 -89
- data/spec/models/doorkeeper/access_grant_spec.rb +0 -144
- data/spec/models/doorkeeper/access_token_spec.rb +0 -591
- data/spec/models/doorkeeper/application_spec.rb +0 -367
- 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 -73
- data/spec/requests/endpoints/token_spec.rb +0 -75
- data/spec/requests/flows/authorization_code_errors_spec.rb +0 -78
- data/spec/requests/flows/authorization_code_spec.rb +0 -447
- data/spec/requests/flows/client_credentials_spec.rb +0 -128
- data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -34
- data/spec/requests/flows/implicit_grant_spec.rb +0 -90
- data/spec/requests/flows/password_spec.rb +0 -259
- data/spec/requests/flows/refresh_token_spec.rb +0 -233
- data/spec/requests/flows/revoke_token_spec.rb +0 -143
- 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 -57
- 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 -98
- data/spec/support/helpers/url_helper.rb +0 -62
- data/spec/support/http_method_shim.rb +0 -29
- data/spec/support/orm/active_record.rb +0 -5
- data/spec/support/shared/controllers_shared_context.rb +0 -123
- 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 -158
- data/spec/version/version_spec.rb +0 -17
data/lib/doorkeeper/config.rb
CHANGED
@@ -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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
32
|
+
# @return [Doorkeeper::Config] configuration instance
|
33
|
+
#
|
34
|
+
def configuration
|
35
|
+
@config || (raise MissingConfiguration)
|
36
|
+
end
|
25
37
|
|
26
|
-
|
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
|
-
|
34
|
-
doorkeeper.
|
35
|
-
|
36
|
-
|
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
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
43
|
-
|
56
|
+
def setup_application_owner
|
57
|
+
@orm_adapter.initialize_application_owner!
|
58
|
+
end
|
44
59
|
end
|
45
60
|
|
46
61
|
class Config
|
47
|
-
|
48
|
-
|
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
|
-
#
|
135
|
-
#
|
136
|
-
#
|
137
|
-
#
|
138
|
-
|
139
|
-
|
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://
|
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://
|
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:
|
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
|
-
|
325
|
-
|
326
|
-
|
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
|
-
#
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
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
|
354
|
-
|
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
|
-
|
573
|
+
authorization_response_flows.map(&:response_type_matches)
|
411
574
|
end
|
412
575
|
|
413
576
|
def token_grant_types
|
414
|
-
|
577
|
+
token_grant_flows.map(&:grant_type_matches)
|
415
578
|
end
|
416
579
|
|
417
|
-
|
418
|
-
|
419
|
-
|
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
|
-
|
426
|
-
|
427
|
-
|
585
|
+
# [NOTE]: deprecated and will be removed soon
|
586
|
+
def deprecated_authorization_flows
|
587
|
+
response_types = calculate_authorization_response_types
|
428
588
|
|
429
|
-
|
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
|
-
|
432
|
-
|
433
|
-
|
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
|
-
#
|
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
|
-
|
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
|
-
#
|
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
|
-
#
|
457
|
-
#
|
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
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
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
|
-
|
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
|
-
|
473
|
-
|
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
|
-
|
480
|
-
|
481
|
-
|
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
|
-
|
484
|
-
|
485
|
-
|
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
|
data/lib/doorkeeper/engine.rb
CHANGED
@@ -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
|
7
|
+
app.config.filter_parameters << /^(#{Regexp.union(parameters)})$/
|
8
8
|
end
|
9
9
|
|
10
10
|
initializer "doorkeeper.routes" do
|
data/lib/doorkeeper/errors.rb
CHANGED
@@ -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
|
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
|
54
|
-
TokenExpired = Class.new
|
55
|
-
TokenRevoked = Class.new
|
56
|
-
TokenUnknown = Class.new
|
57
|
-
TokenForbidden = Class.new
|
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
|