doorkeeper 5.0.0 → 5.1.0
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.
- checksums.yaml +5 -5
- data/.hound.yml +2 -1
- data/.rubocop.yml +37 -4
- data/.travis.yml +16 -21
- data/Appraisals +29 -7
- data/Dangerfile +67 -0
- data/Gemfile +19 -5
- data/NEWS.md +107 -10
- data/README.md +75 -470
- data/Rakefile +10 -8
- data/app/controllers/doorkeeper/application_controller.rb +3 -2
- data/app/controllers/doorkeeper/application_metal_controller.rb +4 -13
- data/app/controllers/doorkeeper/applications_controller.rb +21 -7
- data/app/controllers/doorkeeper/authorizations_controller.rb +3 -3
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -0
- data/app/controllers/doorkeeper/token_info_controller.rb +4 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +13 -11
- data/app/helpers/doorkeeper/dashboard_helper.rb +3 -1
- data/app/validators/redirect_uri_validator.rb +7 -2
- data/app/views/doorkeeper/applications/_form.html.erb +6 -0
- data/app/views/doorkeeper/applications/show.html.erb +1 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
- data/bin/console +16 -0
- data/config/locales/en.yml +1 -0
- data/doorkeeper.gemspec +28 -24
- data/gemfiles/rails_5_0.gemfile +9 -4
- data/gemfiles/rails_5_1.gemfile +9 -4
- data/gemfiles/rails_5_2.gemfile +10 -5
- data/gemfiles/rails_6_0.gemfile +17 -0
- data/gemfiles/rails_master.gemfile +9 -9
- data/lib/doorkeeper/config/option.rb +64 -0
- data/lib/doorkeeper/config.rb +197 -76
- data/lib/doorkeeper/engine.rb +3 -1
- data/lib/doorkeeper/errors.rb +17 -0
- data/lib/doorkeeper/grape/authorization_decorator.rb +6 -4
- data/lib/doorkeeper/grape/helpers.rb +5 -3
- data/lib/doorkeeper/helpers/controller.rb +5 -2
- data/lib/doorkeeper/models/access_grant_mixin.rb +25 -6
- data/lib/doorkeeper/models/access_token_mixin.rb +68 -22
- data/lib/doorkeeper/models/application_mixin.rb +45 -1
- data/lib/doorkeeper/models/concerns/accessible.rb +2 -0
- data/lib/doorkeeper/models/concerns/expirable.rb +6 -2
- data/lib/doorkeeper/models/concerns/orderable.rb +2 -0
- data/lib/doorkeeper/models/concerns/ownership.rb +3 -6
- data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
- data/lib/doorkeeper/models/concerns/revocable.rb +4 -1
- data/lib/doorkeeper/models/concerns/scopes.rb +7 -1
- data/lib/doorkeeper/models/concerns/secret_storable.rb +108 -0
- data/lib/doorkeeper/oauth/authorization/code.rb +4 -2
- data/lib/doorkeeper/oauth/authorization/context.rb +2 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +14 -7
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +3 -1
- data/lib/doorkeeper/oauth/authorization_code_request.rb +8 -4
- data/lib/doorkeeper/oauth/base_request.rb +2 -0
- data/lib/doorkeeper/oauth/base_response.rb +2 -0
- data/lib/doorkeeper/oauth/client/credentials.rb +2 -0
- data/lib/doorkeeper/oauth/client.rb +3 -1
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -0
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +2 -0
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +7 -4
- data/lib/doorkeeper/oauth/client_credentials_request.rb +3 -1
- data/lib/doorkeeper/oauth/code_request.rb +2 -0
- data/lib/doorkeeper/oauth/code_response.rb +4 -2
- data/lib/doorkeeper/oauth/error.rb +2 -0
- data/lib/doorkeeper/oauth/error_response.rb +20 -6
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +10 -3
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +25 -8
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +15 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +42 -3
- data/lib/doorkeeper/oauth/invalid_token_response.rb +22 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +9 -2
- data/lib/doorkeeper/oauth/pre_authorization.rb +13 -5
- data/lib/doorkeeper/oauth/refresh_token_request.rb +15 -4
- data/lib/doorkeeper/oauth/scopes.rb +7 -3
- data/lib/doorkeeper/oauth/token.rb +4 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +76 -8
- data/lib/doorkeeper/oauth/token_request.rb +2 -0
- data/lib/doorkeeper/oauth/token_response.rb +11 -9
- data/lib/doorkeeper/oauth.rb +5 -5
- data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -13
- data/lib/doorkeeper/orm/active_record/access_token.rb +6 -13
- data/lib/doorkeeper/orm/active_record/application.rb +26 -7
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +10 -3
- data/lib/doorkeeper/orm/active_record.rb +8 -6
- data/lib/doorkeeper/rails/helpers.rb +5 -1
- data/lib/doorkeeper/rails/routes/mapper.rb +2 -0
- data/lib/doorkeeper/rails/routes/mapping.rb +9 -7
- data/lib/doorkeeper/rails/routes.rb +19 -12
- data/lib/doorkeeper/rake/db.rake +17 -17
- data/lib/doorkeeper/rake.rb +1 -1
- data/lib/doorkeeper/request/authorization_code.rb +2 -0
- data/lib/doorkeeper/request/client_credentials.rb +2 -0
- data/lib/doorkeeper/request/code.rb +2 -0
- data/lib/doorkeeper/request/password.rb +2 -0
- data/lib/doorkeeper/request/refresh_token.rb +2 -0
- data/lib/doorkeeper/request/strategy.rb +2 -0
- data/lib/doorkeeper/request/token.rb +2 -0
- data/lib/doorkeeper/request.rb +3 -1
- data/lib/doorkeeper/secret_storing/base.rb +64 -0
- data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
- data/lib/doorkeeper/secret_storing/plain.rb +33 -0
- data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
- data/lib/doorkeeper/server.rb +2 -0
- data/lib/doorkeeper/stale_records_cleaner.rb +20 -0
- data/lib/doorkeeper/validations.rb +2 -0
- data/lib/doorkeeper/version.rb +4 -2
- data/lib/doorkeeper.rb +69 -59
- data/lib/generators/doorkeeper/application_owner_generator.rb +10 -9
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +10 -9
- data/lib/generators/doorkeeper/install_generator.rb +11 -9
- data/lib/generators/doorkeeper/migration_generator.rb +9 -9
- data/lib/generators/doorkeeper/pkce_generator.rb +10 -9
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +10 -9
- data/lib/generators/doorkeeper/templates/initializer.rb +138 -13
- data/lib/generators/doorkeeper/templates/migration.rb.erb +17 -10
- data/lib/generators/doorkeeper/views_generator.rb +6 -4
- data/spec/controllers/application_metal_controller_spec.rb +24 -10
- data/spec/controllers/applications_controller_spec.rb +76 -78
- data/spec/controllers/authorizations_controller_spec.rb +189 -142
- data/spec/controllers/protected_resources_controller_spec.rb +111 -67
- data/spec/controllers/token_info_controller_spec.rb +14 -12
- data/spec/controllers/tokens_controller_spec.rb +170 -112
- data/spec/dummy/Rakefile +3 -1
- data/spec/dummy/app/controllers/application_controller.rb +3 -1
- data/spec/dummy/app/controllers/custom_authorizations_controller.rb +3 -1
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -2
- data/spec/dummy/app/controllers/home_controller.rb +6 -5
- data/spec/dummy/app/controllers/metal_controller.rb +2 -0
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +4 -2
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/user.rb +2 -0
- data/spec/dummy/config/application.rb +26 -2
- data/spec/dummy/config/boot.rb +2 -4
- data/spec/dummy/config/environment.rb +1 -1
- data/spec/dummy/config/environments/development.rb +2 -0
- data/spec/dummy/config/environments/production.rb +2 -0
- data/spec/dummy/config/environments/test.rb +4 -2
- data/spec/dummy/config/initializers/backtrace_silencers.rb +2 -0
- data/spec/dummy/config/initializers/doorkeeper.rb +7 -3
- data/spec/dummy/config/initializers/secret_token.rb +3 -1
- data/spec/dummy/config/initializers/session_store.rb +3 -1
- data/spec/dummy/config/initializers/wrap_parameters.rb +2 -0
- data/spec/dummy/config.ru +3 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +20 -13
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +1 -1
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +2 -0
- data/spec/dummy/db/schema.rb +1 -1
- data/spec/dummy/script/rails +7 -4
- data/spec/factories.rb +11 -9
- data/spec/generators/application_owner_generator_spec.rb +13 -26
- data/spec/generators/confidential_applications_generator_spec.rb +12 -28
- data/spec/generators/install_generator_spec.rb +19 -14
- data/spec/generators/migration_generator_spec.rb +13 -26
- data/spec/generators/pkce_generator_spec.rb +11 -26
- data/spec/generators/previous_refresh_token_generator_spec.rb +16 -29
- data/spec/generators/templates/routes.rb +2 -1
- data/spec/generators/views_generator_spec.rb +14 -12
- data/spec/grape/grape_integration_spec.rb +35 -33
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +9 -7
- data/spec/lib/config_spec.rb +290 -104
- data/spec/lib/doorkeeper_spec.rb +8 -6
- data/spec/lib/models/expirable_spec.rb +22 -8
- data/spec/lib/models/reusable_spec.rb +40 -0
- data/spec/lib/models/revocable_spec.rb +8 -6
- data/spec/lib/models/scopes_spec.rb +27 -13
- data/spec/lib/models/secret_storable_spec.rb +135 -0
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +17 -15
- data/spec/lib/oauth/authorization_code_request_spec.rb +43 -17
- data/spec/lib/oauth/base_request_spec.rb +24 -12
- data/spec/lib/oauth/base_response_spec.rb +3 -1
- data/spec/lib/oauth/client/credentials_spec.rb +26 -24
- data/spec/lib/oauth/client_credentials/creator_spec.rb +56 -10
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +27 -20
- data/spec/lib/oauth/client_credentials/validation_spec.rb +21 -15
- data/spec/lib/oauth/client_credentials_integration_spec.rb +8 -6
- data/spec/lib/oauth/client_credentials_request_spec.rb +27 -21
- data/spec/lib/oauth/client_spec.rb +15 -13
- data/spec/lib/oauth/code_request_spec.rb +10 -8
- data/spec/lib/oauth/code_response_spec.rb +9 -7
- data/spec/lib/oauth/error_response_spec.rb +19 -11
- data/spec/lib/oauth/error_spec.rb +4 -2
- data/spec/lib/oauth/forbidden_token_response_spec.rb +7 -5
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +68 -31
- data/spec/lib/oauth/helpers/unique_token_spec.rb +8 -6
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +124 -93
- data/spec/lib/oauth/invalid_token_response_spec.rb +3 -1
- data/spec/lib/oauth/password_access_token_request_spec.rb +95 -34
- data/spec/lib/oauth/pre_authorization_spec.rb +80 -54
- data/spec/lib/oauth/refresh_token_request_spec.rb +46 -39
- data/spec/lib/oauth/scopes_spec.rb +63 -61
- data/spec/lib/oauth/token_request_spec.rb +80 -25
- data/spec/lib/oauth/token_response_spec.rb +40 -38
- data/spec/lib/oauth/token_spec.rb +64 -45
- data/spec/lib/request/strategy_spec.rb +3 -1
- data/spec/lib/secret_storing/base_spec.rb +60 -0
- data/spec/lib/secret_storing/bcrypt_spec.rb +49 -0
- data/spec/lib/secret_storing/plain_spec.rb +44 -0
- data/spec/lib/secret_storing/sha256_hash_spec.rb +48 -0
- data/spec/lib/server_spec.rb +20 -18
- data/spec/lib/{orm/active_record/stale_records_cleaner_spec.rb → stale_records_cleaner_spec.rb} +28 -18
- data/spec/models/doorkeeper/access_grant_spec.rb +80 -15
- data/spec/models/doorkeeper/access_token_spec.rb +212 -83
- data/spec/models/doorkeeper/application_spec.rb +146 -49
- data/spec/requests/applications/applications_request_spec.rb +100 -68
- data/spec/requests/applications/authorized_applications_spec.rb +20 -18
- data/spec/requests/endpoints/authorization_spec.rb +27 -25
- data/spec/requests/endpoints/token_spec.rb +38 -36
- data/spec/requests/flows/authorization_code_errors_spec.rb +27 -25
- data/spec/requests/flows/authorization_code_spec.rb +260 -158
- data/spec/requests/flows/client_credentials_spec.rb +54 -52
- data/spec/requests/flows/implicit_grant_errors_spec.rb +11 -9
- data/spec/requests/flows/implicit_grant_spec.rb +27 -25
- data/spec/requests/flows/password_spec.rb +64 -56
- data/spec/requests/flows/refresh_token_spec.rb +91 -32
- data/spec/requests/flows/revoke_token_spec.rb +49 -63
- data/spec/requests/flows/skip_authorization_spec.rb +23 -21
- data/spec/requests/protected_resources/metal_spec.rb +7 -5
- data/spec/requests/protected_resources/private_api_spec.rb +37 -35
- data/spec/routing/custom_controller_routes_spec.rb +71 -65
- data/spec/routing/default_routes_spec.rb +22 -20
- data/spec/routing/scoped_routes_spec.rb +20 -18
- data/spec/spec_helper.rb +15 -13
- data/spec/spec_helper_integration.rb +3 -1
- data/spec/support/dependencies/factory_bot.rb +3 -1
- data/spec/support/doorkeeper_rspec.rb +5 -2
- data/spec/support/helpers/access_token_request_helper.rb +3 -1
- data/spec/support/helpers/authorization_request_helper.rb +4 -2
- data/spec/support/helpers/config_helper.rb +2 -0
- data/spec/support/helpers/model_helper.rb +11 -5
- data/spec/support/helpers/request_spec_helper.rb +5 -3
- data/spec/support/helpers/url_helper.rb +20 -18
- data/spec/support/http_method_shim.rb +4 -9
- data/spec/support/orm/active_record.rb +3 -1
- data/spec/support/shared/controllers_shared_context.rb +68 -10
- data/spec/support/shared/hashing_shared_context.rb +36 -0
- data/spec/support/shared/models_shared_examples.rb +12 -10
- data/spec/validators/redirect_uri_validator_spec.rb +76 -47
- data/spec/version/version_spec.rb +7 -5
- metadata +70 -21
- data/gemfiles/rails_4_2.gemfile +0 -13
- data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -10
data/lib/doorkeeper/config.rb
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "doorkeeper/config/option"
|
|
4
|
+
|
|
1
5
|
module Doorkeeper
|
|
2
6
|
class MissingConfiguration < StandardError
|
|
3
7
|
# Defines a MissingConfiguration error for a missing Doorkeeper
|
|
4
8
|
# configuration
|
|
5
9
|
def initialize
|
|
6
|
-
super(
|
|
10
|
+
super("Configuration for doorkeeper missing. Do you have doorkeeper initializer?")
|
|
7
11
|
end
|
|
8
12
|
end
|
|
9
13
|
|
|
@@ -12,6 +16,7 @@ module Doorkeeper
|
|
|
12
16
|
setup_orm_adapter
|
|
13
17
|
setup_orm_models
|
|
14
18
|
setup_application_owner if @config.enable_application_owner?
|
|
19
|
+
@config
|
|
15
20
|
end
|
|
16
21
|
|
|
17
22
|
def self.configuration
|
|
@@ -46,6 +51,7 @@ module Doorkeeper
|
|
|
46
51
|
end
|
|
47
52
|
|
|
48
53
|
def build
|
|
54
|
+
@config.validate
|
|
49
55
|
@config
|
|
50
56
|
end
|
|
51
57
|
|
|
@@ -83,6 +89,13 @@ module Doorkeeper
|
|
|
83
89
|
@config.instance_variable_set(:@optional_scopes, OAuth::Scopes.from_array(scopes))
|
|
84
90
|
end
|
|
85
91
|
|
|
92
|
+
# Define scopes_by_grant_type to limit certain scope to certain grant_type
|
|
93
|
+
# @param { Hash } with grant_types as keys.
|
|
94
|
+
# Default set to {} i.e. no limitation on scopes usage
|
|
95
|
+
def scopes_by_grant_type(hash = {})
|
|
96
|
+
@config.instance_variable_set(:@scopes_by_grant_type, hash)
|
|
97
|
+
end
|
|
98
|
+
|
|
86
99
|
# Change the way client credentials are retrieved from the request object.
|
|
87
100
|
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
|
|
88
101
|
# falls back to the `:client_id` and `:client_secret` params from the
|
|
@@ -107,7 +120,7 @@ module Doorkeeper
|
|
|
107
120
|
def use_refresh_token(enabled = true, &block)
|
|
108
121
|
@config.instance_variable_set(
|
|
109
122
|
:@refresh_token_enabled,
|
|
110
|
-
block
|
|
123
|
+
block || enabled
|
|
111
124
|
)
|
|
112
125
|
end
|
|
113
126
|
|
|
@@ -118,6 +131,15 @@ module Doorkeeper
|
|
|
118
131
|
@config.instance_variable_set(:@reuse_access_token, true)
|
|
119
132
|
end
|
|
120
133
|
|
|
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)
|
|
141
|
+
end
|
|
142
|
+
|
|
121
143
|
# Use an API mode for applications generated with --api argument
|
|
122
144
|
# It will skip applications controller, disable forgery protection
|
|
123
145
|
def api_only
|
|
@@ -136,63 +158,54 @@ module Doorkeeper
|
|
|
136
158
|
def enforce_content_type
|
|
137
159
|
@config.instance_variable_set(:@enforce_content_type, true)
|
|
138
160
|
end
|
|
139
|
-
end
|
|
140
161
|
|
|
141
|
-
|
|
142
|
-
#
|
|
143
|
-
#
|
|
144
|
-
# When you call option, it defines two methods. One method will take place
|
|
145
|
-
# in the +Config+ class and the other method will take place in the
|
|
146
|
-
# +Builder+ class.
|
|
162
|
+
# Allow optional hashing of input tokens before persisting them.
|
|
163
|
+
# Will be used for hashing of input token and grants.
|
|
147
164
|
#
|
|
148
|
-
#
|
|
149
|
-
#
|
|
150
|
-
#
|
|
151
|
-
#
|
|
152
|
-
#
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
#
|
|
161
|
-
#
|
|
162
|
-
# ==== Examples
|
|
163
|
-
#
|
|
164
|
-
# option :name
|
|
165
|
-
# option :name, as: :set_name
|
|
166
|
-
# option :name, default: 'My Name'
|
|
167
|
-
# option :scopes builder_class: ScopesBuilder
|
|
165
|
+
# @param using
|
|
166
|
+
# Provide a different secret storage implementation class for tokens
|
|
167
|
+
# @param fallback
|
|
168
|
+
# Provide a fallback secret storage implementation class for tokens
|
|
169
|
+
# or use :plain to fallback to plain tokens
|
|
170
|
+
def hash_token_secrets(using: nil, fallback: nil)
|
|
171
|
+
default = "::Doorkeeper::SecretStoring::Sha256Hash"
|
|
172
|
+
configure_secrets_for :token,
|
|
173
|
+
using: using || default,
|
|
174
|
+
fallback: fallback
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Allow optional hashing of application secrets before persisting them.
|
|
178
|
+
# Will be used for hashing of input token and grants.
|
|
168
179
|
#
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
180
|
+
# @param using
|
|
181
|
+
# Provide a different secret storage implementation for applications
|
|
182
|
+
# @param fallback
|
|
183
|
+
# Provide a fallback secret storage implementation for applications
|
|
184
|
+
# or use :plain to fallback to plain application secrets
|
|
185
|
+
def hash_application_secrets(using: nil, fallback: nil)
|
|
186
|
+
default = "::Doorkeeper::SecretStoring::Sha256Hash"
|
|
187
|
+
configure_secrets_for :application,
|
|
188
|
+
using: using || default,
|
|
189
|
+
fallback: fallback
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
private
|
|
193
|
+
|
|
194
|
+
# Configure the secret storing functionality
|
|
195
|
+
def configure_secrets_for(type, using:, fallback:)
|
|
196
|
+
raise ArgumentError, "Invalid type #{type}" if %i[application token].exclude?(type)
|
|
186
197
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
198
|
+
@config.instance_variable_set(:"@#{type}_secret_strategy",
|
|
199
|
+
using.constantize)
|
|
200
|
+
|
|
201
|
+
if fallback.nil?
|
|
202
|
+
return
|
|
203
|
+
elsif fallback.to_sym == :plain
|
|
204
|
+
fallback = "::Doorkeeper::SecretStoring::Plain"
|
|
193
205
|
end
|
|
194
206
|
|
|
195
|
-
|
|
207
|
+
@config.instance_variable_set(:"@#{type}_secret_fallback_strategy",
|
|
208
|
+
fallback.constantize)
|
|
196
209
|
end
|
|
197
210
|
end
|
|
198
211
|
|
|
@@ -202,7 +215,7 @@ module Doorkeeper
|
|
|
202
215
|
as: :authenticate_resource_owner,
|
|
203
216
|
default: (lambda do |_routes|
|
|
204
217
|
::Rails.logger.warn(
|
|
205
|
-
I18n.t(
|
|
218
|
+
I18n.t("doorkeeper.errors.messages.resource_owner_authenticator_not_configured")
|
|
206
219
|
)
|
|
207
220
|
|
|
208
221
|
nil
|
|
@@ -212,7 +225,7 @@ module Doorkeeper
|
|
|
212
225
|
as: :authenticate_admin,
|
|
213
226
|
default: (lambda do |_routes|
|
|
214
227
|
::Rails.logger.warn(
|
|
215
|
-
I18n.t(
|
|
228
|
+
I18n.t("doorkeeper.errors.messages.admin_authenticator_not_configured")
|
|
216
229
|
)
|
|
217
230
|
|
|
218
231
|
head :forbidden
|
|
@@ -221,24 +234,30 @@ module Doorkeeper
|
|
|
221
234
|
option :resource_owner_from_credentials,
|
|
222
235
|
default: (lambda do |_routes|
|
|
223
236
|
::Rails.logger.warn(
|
|
224
|
-
I18n.t(
|
|
237
|
+
I18n.t("doorkeeper.errors.messages.credential_flow_not_configured")
|
|
225
238
|
)
|
|
226
239
|
|
|
227
240
|
nil
|
|
228
241
|
end)
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
option :
|
|
232
|
-
option :
|
|
233
|
-
|
|
242
|
+
|
|
243
|
+
# Hooks for authorization
|
|
244
|
+
option :before_successful_authorization, default: ->(_context) {}
|
|
245
|
+
option :after_successful_authorization, default: ->(_context) {}
|
|
246
|
+
# Hooks for strategies responses
|
|
247
|
+
option :before_successful_strategy_response, default: ->(_request) {}
|
|
248
|
+
option :after_successful_strategy_response, default: ->(_request, _response) {}
|
|
249
|
+
# Allows to customize Token Introspection response
|
|
250
|
+
option :custom_introspection_response, default: ->(_token, _context) { {} }
|
|
251
|
+
|
|
234
252
|
option :skip_authorization, default: ->(_routes) {}
|
|
235
253
|
option :access_token_expires_in, default: 7200
|
|
236
254
|
option :custom_access_token_expires_in, default: ->(_context) { nil }
|
|
237
255
|
option :authorization_code_expires_in, default: 600
|
|
238
256
|
option :orm, default: :active_record
|
|
239
|
-
option :native_redirect_uri, default:
|
|
257
|
+
option :native_redirect_uri, default: "urn:ietf:wg:oauth:2.0:oob"
|
|
240
258
|
option :active_record_options, default: {}
|
|
241
259
|
option :grant_flows, default: %w[authorization_code client_credentials]
|
|
260
|
+
option :handle_auth_errors, default: :render
|
|
242
261
|
|
|
243
262
|
# Allows to forbid specific Application redirect URI's by custom rules.
|
|
244
263
|
# Doesn't forbid any URI by default.
|
|
@@ -251,7 +270,7 @@ module Doorkeeper
|
|
|
251
270
|
#
|
|
252
271
|
# @param realm [String] ("Doorkeeper") Authentication realm
|
|
253
272
|
#
|
|
254
|
-
option :realm, default:
|
|
273
|
+
option :realm, default: "Doorkeeper"
|
|
255
274
|
|
|
256
275
|
# Forces the usage of the HTTPS protocol in non-native redirect uris
|
|
257
276
|
# (enabled by default in non-development environments). OAuth2
|
|
@@ -275,7 +294,15 @@ module Doorkeeper
|
|
|
275
294
|
# the name of the access token generator class
|
|
276
295
|
#
|
|
277
296
|
option :access_token_generator,
|
|
278
|
-
default:
|
|
297
|
+
default: "Doorkeeper::OAuth::Helpers::UniqueToken"
|
|
298
|
+
|
|
299
|
+
# Default access token generator is a SecureRandom class from Ruby stdlib.
|
|
300
|
+
# This option defines which method will be used to generate a unique token value.
|
|
301
|
+
#
|
|
302
|
+
# @param access_token_generator [String]
|
|
303
|
+
# the name of the access token generator class
|
|
304
|
+
#
|
|
305
|
+
option :default_generator_method, default: :urlsafe_base64
|
|
279
306
|
|
|
280
307
|
# The controller Doorkeeper::ApplicationController inherits from.
|
|
281
308
|
# Defaults to ActionController::Base.
|
|
@@ -283,11 +310,29 @@ module Doorkeeper
|
|
|
283
310
|
#
|
|
284
311
|
# @param base_controller [String] the name of the base controller
|
|
285
312
|
option :base_controller,
|
|
286
|
-
default:
|
|
313
|
+
default: "ActionController::Base"
|
|
287
314
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
315
|
+
# Allows to set blank redirect URIs for Applications in case
|
|
316
|
+
# server configured to use URI-less grant flows.
|
|
317
|
+
#
|
|
318
|
+
option :allow_blank_redirect_uri,
|
|
319
|
+
default: (lambda do |grant_flows, _application|
|
|
320
|
+
grant_flows.exclude?("authorization_code") &&
|
|
321
|
+
grant_flows.exclude?("implicit")
|
|
322
|
+
end)
|
|
323
|
+
|
|
324
|
+
attr_reader :api_only,
|
|
325
|
+
:enforce_content_type,
|
|
326
|
+
:reuse_access_token,
|
|
327
|
+
:token_secret_fallback_strategy,
|
|
328
|
+
:application_secret_fallback_strategy
|
|
329
|
+
|
|
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
|
|
335
|
+
end
|
|
291
336
|
|
|
292
337
|
def api_only
|
|
293
338
|
@api_only ||= false
|
|
@@ -305,16 +350,32 @@ module Doorkeeper
|
|
|
305
350
|
end
|
|
306
351
|
end
|
|
307
352
|
|
|
353
|
+
def token_reuse_limit
|
|
354
|
+
@token_reuse_limit ||= 100
|
|
355
|
+
end
|
|
356
|
+
|
|
308
357
|
def enforce_configured_scopes?
|
|
309
|
-
|
|
358
|
+
option_set? :enforce_configured_scopes
|
|
310
359
|
end
|
|
311
360
|
|
|
312
361
|
def enable_application_owner?
|
|
313
|
-
|
|
362
|
+
option_set? :enable_application_owner
|
|
314
363
|
end
|
|
315
364
|
|
|
316
365
|
def confirm_application_owner?
|
|
317
|
-
|
|
366
|
+
option_set? :confirm_application_owner
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def raise_on_errors?
|
|
370
|
+
handle_auth_errors == :raise
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def token_secret_strategy
|
|
374
|
+
@token_secret_strategy ||= ::Doorkeeper::SecretStoring::Plain
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
def application_secret_strategy
|
|
378
|
+
@application_secret_strategy ||= ::Doorkeeper::SecretStoring::Plain
|
|
318
379
|
end
|
|
319
380
|
|
|
320
381
|
def default_scopes
|
|
@@ -329,12 +390,20 @@ module Doorkeeper
|
|
|
329
390
|
@scopes ||= default_scopes + optional_scopes
|
|
330
391
|
end
|
|
331
392
|
|
|
393
|
+
def scopes_by_grant_type
|
|
394
|
+
@scopes_by_grant_type ||= {}
|
|
395
|
+
end
|
|
396
|
+
|
|
332
397
|
def client_credentials_methods
|
|
333
398
|
@client_credentials_methods ||= %i[from_basic from_params]
|
|
334
399
|
end
|
|
335
400
|
|
|
336
401
|
def access_token_methods
|
|
337
|
-
@access_token_methods ||= %i[
|
|
402
|
+
@access_token_methods ||= %i[
|
|
403
|
+
from_bearer_authorization
|
|
404
|
+
from_access_token_param
|
|
405
|
+
from_bearer_param
|
|
406
|
+
]
|
|
338
407
|
end
|
|
339
408
|
|
|
340
409
|
def authorization_response_types
|
|
@@ -345,15 +414,33 @@ module Doorkeeper
|
|
|
345
414
|
@token_grant_types ||= calculate_token_grant_types.freeze
|
|
346
415
|
end
|
|
347
416
|
|
|
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
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
def option_defined?(name)
|
|
426
|
+
instance_variable_defined?("@#{name}")
|
|
427
|
+
end
|
|
428
|
+
|
|
348
429
|
private
|
|
349
430
|
|
|
431
|
+
# Helper to read boolearized configuration option
|
|
432
|
+
def option_set?(instance_key)
|
|
433
|
+
var = instance_variable_get("@#{instance_key}")
|
|
434
|
+
!!(defined?(var) && var)
|
|
435
|
+
end
|
|
436
|
+
|
|
350
437
|
# Determines what values are acceptable for 'response_type' param in
|
|
351
438
|
# authorization request endpoint, and return them as an array of strings.
|
|
352
439
|
#
|
|
353
440
|
def calculate_authorization_response_types
|
|
354
441
|
types = []
|
|
355
|
-
types <<
|
|
356
|
-
types <<
|
|
442
|
+
types << "code" if grant_flows.include? "authorization_code"
|
|
443
|
+
types << "token" if grant_flows.include? "implicit"
|
|
357
444
|
types
|
|
358
445
|
end
|
|
359
446
|
|
|
@@ -361,9 +448,43 @@ module Doorkeeper
|
|
|
361
448
|
# request endpoint, and return them in array.
|
|
362
449
|
#
|
|
363
450
|
def calculate_token_grant_types
|
|
364
|
-
types = grant_flows - [
|
|
365
|
-
types <<
|
|
451
|
+
types = grant_flows - ["implicit"]
|
|
452
|
+
types << "refresh_token" if refresh_token_enabled?
|
|
366
453
|
types
|
|
367
454
|
end
|
|
455
|
+
|
|
456
|
+
# Determine whether +reuse_access_token+ and a non-restorable
|
|
457
|
+
# +token_secret_strategy+ have both been activated.
|
|
458
|
+
#
|
|
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?
|
|
463
|
+
|
|
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
|
|
470
|
+
end
|
|
471
|
+
|
|
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
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
def validate_token_reuse_limit
|
|
480
|
+
return if !reuse_access_token ||
|
|
481
|
+
(token_reuse_limit > 0 && token_reuse_limit <= 100)
|
|
482
|
+
|
|
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
|
|
488
|
+
end
|
|
368
489
|
end
|
|
369
490
|
end
|
data/lib/doorkeeper/engine.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
class Engine < Rails::Engine
|
|
3
5
|
initializer "doorkeeper.params.filter" do |app|
|
|
@@ -16,7 +18,7 @@ module Doorkeeper
|
|
|
16
18
|
end
|
|
17
19
|
|
|
18
20
|
if defined?(Sprockets) && Sprockets::VERSION.chr.to_i >= 4
|
|
19
|
-
initializer
|
|
21
|
+
initializer "doorkeeper.assets.precompile" do |app|
|
|
20
22
|
# Force users to use:
|
|
21
23
|
# //= link doorkeeper/admin/application.css
|
|
22
24
|
# in Doorkeeper 5 for Sprockets 4 instead of precompile.
|
data/lib/doorkeeper/errors.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
module Errors
|
|
3
5
|
class DoorkeeperError < StandardError
|
|
@@ -36,7 +38,22 @@ module Doorkeeper
|
|
|
36
38
|
end
|
|
37
39
|
end
|
|
38
40
|
|
|
41
|
+
class BaseResponseError < DoorkeeperError
|
|
42
|
+
attr_reader :response
|
|
43
|
+
|
|
44
|
+
def initialize(response)
|
|
45
|
+
@response = response
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
39
49
|
UnableToGenerateToken = Class.new(DoorkeeperError)
|
|
40
50
|
TokenGeneratorNotFound = Class.new(DoorkeeperError)
|
|
51
|
+
NoOrmCleaner = Class.new(DoorkeeperError)
|
|
52
|
+
|
|
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
|
|
41
58
|
end
|
|
42
59
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
module Grape
|
|
3
5
|
class AuthorizationDecorator < SimpleDelegator
|
|
@@ -7,10 +9,10 @@ module Doorkeeper
|
|
|
7
9
|
|
|
8
10
|
def authorization
|
|
9
11
|
env = __getobj__.env
|
|
10
|
-
env[
|
|
11
|
-
env[
|
|
12
|
-
env[
|
|
13
|
-
env[
|
|
12
|
+
env["HTTP_AUTHORIZATION"] ||
|
|
13
|
+
env["X-HTTP_AUTHORIZATION"] ||
|
|
14
|
+
env["X_HTTP_AUTHORIZATION"] ||
|
|
15
|
+
env["REDIRECT_X_HTTP_AUTHORIZATION"]
|
|
14
16
|
end
|
|
15
17
|
end
|
|
16
18
|
end
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "doorkeeper/grape/authorization_decorator"
|
|
2
4
|
|
|
3
5
|
module Doorkeeper
|
|
4
6
|
module Grape
|
|
@@ -27,7 +29,7 @@ module Doorkeeper
|
|
|
27
29
|
private
|
|
28
30
|
|
|
29
31
|
def endpoint
|
|
30
|
-
env[
|
|
32
|
+
env["api.endpoint"]
|
|
31
33
|
end
|
|
32
34
|
|
|
33
35
|
def doorkeeper_token
|
|
@@ -44,7 +46,7 @@ module Doorkeeper
|
|
|
44
46
|
def error_status_codes
|
|
45
47
|
{
|
|
46
48
|
unauthorized: 401,
|
|
47
|
-
forbidden: 403
|
|
49
|
+
forbidden: 403,
|
|
48
50
|
}
|
|
49
51
|
end
|
|
50
52
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Define methods that can be called in any controller that inherits from
|
|
2
4
|
# Doorkeeper::ApplicationMetalController or Doorkeeper::ApplicationController
|
|
3
5
|
module Doorkeeper
|
|
@@ -53,8 +55,9 @@ module Doorkeeper
|
|
|
53
55
|
end
|
|
54
56
|
|
|
55
57
|
def enforce_content_type
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
if (request.put? || request.post? || request.patch?) && request.content_type != "application/x-www-form-urlencoded"
|
|
59
|
+
render json: {}, status: :unsupported_media_type
|
|
60
|
+
end
|
|
58
61
|
end
|
|
59
62
|
end
|
|
60
63
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
module AccessGrantMixin
|
|
3
5
|
extend ActiveSupport::Concern
|
|
@@ -7,6 +9,7 @@ module Doorkeeper
|
|
|
7
9
|
include Models::Revocable
|
|
8
10
|
include Models::Accessible
|
|
9
11
|
include Models::Orderable
|
|
12
|
+
include Models::SecretStorable
|
|
10
13
|
include Models::Scopes
|
|
11
14
|
|
|
12
15
|
# never uses pkce, if pkce migrations were not generated
|
|
@@ -28,7 +31,7 @@ module Doorkeeper
|
|
|
28
31
|
# if there is no record with such token
|
|
29
32
|
#
|
|
30
33
|
def by_token(token)
|
|
31
|
-
|
|
34
|
+
find_by_plaintext_token(:token, token)
|
|
32
35
|
end
|
|
33
36
|
|
|
34
37
|
# Revokes AccessGrant records that have not been revoked and associated
|
|
@@ -42,8 +45,8 @@ module Doorkeeper
|
|
|
42
45
|
def revoke_all_for(application_id, resource_owner, clock = Time)
|
|
43
46
|
where(application_id: application_id,
|
|
44
47
|
resource_owner_id: resource_owner.id,
|
|
45
|
-
revoked_at: nil)
|
|
46
|
-
update_all(revoked_at: clock.now.utc)
|
|
48
|
+
revoked_at: nil)
|
|
49
|
+
.update_all(revoked_at: clock.now.utc)
|
|
47
50
|
end
|
|
48
51
|
|
|
49
52
|
# Implements PKCE code_challenge encoding without base64 padding as described in the spec.
|
|
@@ -78,20 +81,36 @@ module Doorkeeper
|
|
|
78
81
|
#
|
|
79
82
|
# urlsafe_encode64(bin)
|
|
80
83
|
# Returns the Base64-encoded version of bin. This method complies with
|
|
81
|
-
#
|
|
84
|
+
# "Base 64 Encoding with URL and Filename Safe Alphabet" in RFC 4648.
|
|
82
85
|
# The alphabet uses '-' instead of '+' and '_' instead of '/'.
|
|
83
86
|
|
|
84
87
|
# @param code_verifier [#to_s] a one time use value (any object that responds to `#to_s`)
|
|
85
88
|
#
|
|
86
|
-
# @return [#to_s] An encoded code challenge based on the provided verifier
|
|
89
|
+
# @return [#to_s] An encoded code challenge based on the provided verifier
|
|
90
|
+
# suitable for PKCE validation
|
|
91
|
+
#
|
|
87
92
|
def generate_code_challenge(code_verifier)
|
|
88
93
|
padded_result = Base64.urlsafe_encode64(Digest::SHA256.digest(code_verifier))
|
|
89
|
-
padded_result.split(
|
|
94
|
+
padded_result.split("=")[0] # Remove any trailing '='
|
|
90
95
|
end
|
|
91
96
|
|
|
92
97
|
def pkce_supported?
|
|
93
98
|
new.pkce_supported?
|
|
94
99
|
end
|
|
100
|
+
|
|
101
|
+
##
|
|
102
|
+
# Determines the secret storing transformer
|
|
103
|
+
# Unless configured otherwise, uses the plain secret strategy
|
|
104
|
+
def secret_strategy
|
|
105
|
+
::Doorkeeper.configuration.token_secret_strategy
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
##
|
|
109
|
+
# Determine the fallback storing strategy
|
|
110
|
+
# Unless configured, there will be no fallback
|
|
111
|
+
def fallback_secret_strategy
|
|
112
|
+
::Doorkeeper.configuration.token_secret_fallback_strategy
|
|
113
|
+
end
|
|
95
114
|
end
|
|
96
115
|
end
|
|
97
116
|
end
|