doorkeeper 4.4.3 → 5.0.3
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 +5 -5
- data/.gitignore +1 -0
- data/.gitlab-ci.yml +16 -0
- data/.travis.yml +7 -0
- data/Appraisals +2 -2
- data/Dangerfile +64 -0
- data/Gemfile +1 -1
- data/NEWS.md +98 -8
- data/README.md +110 -12
- data/Rakefile +6 -0
- data/UPGRADE.md +2 -0
- data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +6 -3
- data/app/controllers/doorkeeper/application_metal_controller.rb +6 -0
- data/app/controllers/doorkeeper/applications_controller.rb +46 -24
- data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +21 -2
- data/app/controllers/doorkeeper/token_info_controller.rb +2 -0
- data/app/controllers/doorkeeper/tokens_controller.rb +4 -6
- data/app/helpers/doorkeeper/dashboard_helper.rb +9 -7
- data/app/validators/redirect_uri_validator.rb +5 -2
- data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
- data/app/views/doorkeeper/applications/_form.html.erb +25 -24
- data/app/views/doorkeeper/applications/edit.html.erb +1 -1
- data/app/views/doorkeeper/applications/index.html.erb +17 -7
- data/app/views/doorkeeper/applications/new.html.erb +1 -1
- data/app/views/doorkeeper/applications/show.html.erb +6 -6
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
- data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
- data/config/locales/en.yml +10 -1
- data/doorkeeper.gemspec +25 -26
- data/gemfiles/rails_5_2.gemfile +1 -1
- data/gemfiles/rails_master.gemfile +4 -1
- data/lib/doorkeeper/config.rb +81 -40
- data/lib/doorkeeper/engine.rb +6 -0
- data/lib/doorkeeper/errors.rb +17 -3
- data/lib/doorkeeper/grape/authorization_decorator.rb +2 -0
- data/lib/doorkeeper/grape/helpers.rb +3 -1
- data/lib/doorkeeper/helpers/controller.rb +9 -2
- data/lib/doorkeeper/models/access_grant_mixin.rb +73 -0
- data/lib/doorkeeper/models/access_token_mixin.rb +44 -25
- data/lib/doorkeeper/models/application_mixin.rb +2 -0
- data/lib/doorkeeper/models/concerns/accessible.rb +2 -0
- data/lib/doorkeeper/models/concerns/expirable.rb +2 -0
- data/lib/doorkeeper/models/concerns/orderable.rb +2 -0
- data/lib/doorkeeper/models/concerns/ownership.rb +2 -0
- data/lib/doorkeeper/models/concerns/revocable.rb +2 -0
- data/lib/doorkeeper/models/concerns/scopes.rb +3 -1
- data/lib/doorkeeper/oauth/authorization/code.rb +33 -8
- data/lib/doorkeeper/oauth/authorization/context.rb +17 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +38 -14
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +2 -0
- data/lib/doorkeeper/oauth/authorization_code_request.rb +29 -2
- data/lib/doorkeeper/oauth/base_request.rb +22 -9
- data/lib/doorkeeper/oauth/base_response.rb +2 -0
- data/lib/doorkeeper/oauth/client/credentials.rb +3 -1
- data/lib/doorkeeper/oauth/client.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +4 -1
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +7 -2
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +5 -5
- data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -3
- data/lib/doorkeeper/oauth/code_request.rb +2 -0
- data/lib/doorkeeper/oauth/code_response.rb +2 -0
- data/lib/doorkeeper/oauth/error.rb +2 -0
- data/lib/doorkeeper/oauth/error_response.rb +21 -3
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +9 -2
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -8
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +2 -0
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +5 -2
- data/lib/doorkeeper/oauth/invalid_token_response.rb +18 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +9 -4
- data/lib/doorkeeper/oauth/pre_authorization.rb +43 -11
- data/lib/doorkeeper/oauth/refresh_token_request.rb +16 -3
- data/lib/doorkeeper/oauth/scopes.rb +3 -1
- data/lib/doorkeeper/oauth/token.rb +7 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +4 -2
- data/lib/doorkeeper/oauth/token_request.rb +2 -0
- data/lib/doorkeeper/oauth/token_response.rb +6 -2
- data/lib/doorkeeper/oauth.rb +13 -0
- data/lib/doorkeeper/orm/active_record/application.rb +75 -12
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
- data/lib/doorkeeper/orm/active_record.rb +4 -0
- data/lib/doorkeeper/rails/helpers.rb +6 -4
- data/lib/doorkeeper/rails/routes/mapper.rb +2 -0
- data/lib/doorkeeper/rails/routes/mapping.rb +2 -0
- data/lib/doorkeeper/rails/routes.rb +23 -8
- data/lib/doorkeeper/rake/db.rake +40 -0
- data/lib/doorkeeper/rake/setup.rake +6 -0
- data/lib/doorkeeper/rake.rb +14 -0
- data/lib/doorkeeper/request/authorization_code.rb +1 -1
- data/lib/doorkeeper/request/client_credentials.rb +1 -1
- data/lib/doorkeeper/request/code.rb +1 -1
- data/lib/doorkeeper/request/password.rb +1 -1
- data/lib/doorkeeper/request/refresh_token.rb +1 -1
- data/lib/doorkeeper/request/strategy.rb +2 -0
- data/lib/doorkeeper/request/token.rb +1 -1
- data/lib/doorkeeper/request.rb +29 -34
- 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 +6 -24
- data/lib/doorkeeper.rb +20 -17
- data/lib/generators/doorkeeper/application_owner_generator.rb +23 -18
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
- data/lib/generators/doorkeeper/install_generator.rb +17 -9
- data/lib/generators/doorkeeper/migration_generator.rb +23 -18
- data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +29 -24
- data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +96 -13
- data/lib/generators/doorkeeper/templates/migration.rb.erb +2 -3
- data/lib/generators/doorkeeper/views_generator.rb +3 -1
- data/spec/controllers/application_metal_controller_spec.rb +50 -0
- data/spec/controllers/applications_controller_spec.rb +123 -14
- data/spec/controllers/authorizations_controller_spec.rb +334 -51
- data/spec/controllers/protected_resources_controller_spec.rb +60 -18
- data/spec/controllers/token_info_controller_spec.rb +4 -12
- data/spec/controllers/tokens_controller_spec.rb +17 -20
- data/spec/dummy/Rakefile +1 -1
- data/spec/dummy/app/assets/config/manifest.js +2 -0
- data/spec/dummy/app/controllers/custom_authorizations_controller.rb +1 -1
- data/spec/dummy/app/controllers/home_controller.rb +1 -2
- data/spec/dummy/config/application.rb +1 -1
- data/spec/dummy/config/boot.rb +2 -4
- data/spec/dummy/config/environment.rb +1 -1
- data/spec/dummy/config/environments/test.rb +5 -6
- data/spec/dummy/config/initializers/doorkeeper.rb +12 -6
- data/spec/dummy/config/initializers/new_framework_defaults.rb +2 -0
- data/spec/dummy/config/initializers/secret_token.rb +1 -1
- data/spec/dummy/config/routes.rb +3 -42
- data/spec/dummy/config.ru +1 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +4 -4
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +1 -1
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
- data/spec/dummy/db/migrate/{20180210183654_add_confidential_to_application.rb → 20180210183654_add_confidential_to_applications.rb} +1 -1
- data/spec/dummy/db/schema.rb +36 -36
- data/spec/dummy/script/rails +4 -3
- data/spec/factories.rb +6 -6
- data/spec/generators/application_owner_generator_spec.rb +1 -1
- data/spec/generators/confidential_applications_generator_spec.rb +45 -0
- data/spec/generators/install_generator_spec.rb +5 -2
- data/spec/generators/migration_generator_spec.rb +1 -1
- data/spec/generators/pkce_generator_spec.rb +43 -0
- data/spec/generators/previous_refresh_token_generator_spec.rb +1 -1
- data/spec/generators/templates/routes.rb +0 -1
- data/spec/generators/views_generator_spec.rb +2 -2
- data/spec/grape/grape_integration_spec.rb +2 -2
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +105 -39
- data/spec/lib/doorkeeper_spec.rb +6 -131
- data/spec/lib/models/expirable_spec.rb +0 -3
- data/spec/lib/models/revocable_spec.rb +0 -2
- data/spec/lib/models/scopes_spec.rb +0 -4
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
- data/spec/lib/oauth/authorization_code_request_spec.rb +17 -7
- data/spec/lib/oauth/base_request_spec.rb +49 -11
- data/spec/lib/oauth/base_response_spec.rb +1 -1
- data/spec/lib/oauth/client/credentials_spec.rb +2 -4
- data/spec/lib/oauth/client_credentials/creator_spec.rb +5 -1
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +24 -7
- data/spec/lib/oauth/client_credentials/validation_spec.rb +4 -4
- data/spec/lib/oauth/client_credentials_integration_spec.rb +2 -2
- data/spec/lib/oauth/client_credentials_request_spec.rb +3 -5
- data/spec/lib/oauth/client_spec.rb +0 -3
- data/spec/lib/oauth/code_request_spec.rb +5 -3
- data/spec/lib/oauth/code_response_spec.rb +1 -1
- data/spec/lib/oauth/error_response_spec.rb +0 -3
- data/spec/lib/oauth/error_spec.rb +0 -2
- data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +8 -11
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +22 -13
- data/spec/lib/oauth/invalid_token_response_spec.rb +1 -4
- data/spec/lib/oauth/password_access_token_request_spec.rb +53 -6
- data/spec/lib/oauth/pre_authorization_spec.rb +33 -4
- data/spec/lib/oauth/refresh_token_request_spec.rb +22 -14
- data/spec/lib/oauth/scopes_spec.rb +0 -3
- data/spec/lib/oauth/token_request_spec.rb +8 -9
- data/spec/lib/oauth/token_response_spec.rb +0 -1
- data/spec/lib/oauth/token_spec.rb +40 -14
- data/spec/lib/request/strategy_spec.rb +0 -1
- data/spec/lib/server_spec.rb +7 -7
- data/spec/lib/stale_records_cleaner_spec.rb +89 -0
- data/spec/models/doorkeeper/access_grant_spec.rb +44 -1
- data/spec/models/doorkeeper/access_token_spec.rb +80 -32
- data/spec/models/doorkeeper/application_spec.rb +293 -221
- data/spec/requests/applications/applications_request_spec.rb +134 -1
- data/spec/requests/applications/authorized_applications_spec.rb +1 -1
- data/spec/requests/endpoints/authorization_spec.rb +3 -3
- data/spec/requests/endpoints/token_spec.rb +7 -5
- data/spec/requests/flows/authorization_code_errors_spec.rb +2 -2
- data/spec/requests/flows/authorization_code_spec.rb +258 -2
- data/spec/requests/flows/client_credentials_spec.rb +46 -6
- data/spec/requests/flows/implicit_grant_errors_spec.rb +3 -3
- data/spec/requests/flows/implicit_grant_spec.rb +38 -11
- data/spec/requests/flows/password_spec.rb +61 -3
- data/spec/requests/flows/refresh_token_spec.rb +59 -2
- data/spec/requests/flows/revoke_token_spec.rb +20 -20
- data/spec/requests/flows/skip_authorization_spec.rb +16 -11
- data/spec/requests/protected_resources/metal_spec.rb +1 -1
- data/spec/requests/protected_resources/private_api_spec.rb +3 -3
- data/spec/routing/custom_controller_routes_spec.rb +59 -7
- data/spec/routing/default_routes_spec.rb +2 -2
- data/spec/routing/scoped_routes_spec.rb +16 -2
- data/spec/spec_helper.rb +54 -3
- data/spec/spec_helper_integration.rb +2 -74
- data/spec/support/dependencies/{factory_girl.rb → factory_bot.rb} +0 -0
- data/spec/support/doorkeeper_rspec.rb +20 -0
- data/spec/support/helpers/authorization_request_helper.rb +4 -4
- data/spec/support/helpers/model_helper.rb +8 -4
- data/spec/support/helpers/request_spec_helper.rb +10 -2
- data/spec/support/helpers/url_helper.rb +18 -14
- data/spec/support/http_method_shim.rb +12 -16
- data/spec/support/shared/controllers_shared_context.rb +56 -0
- data/spec/validators/redirect_uri_validator_spec.rb +9 -3
- data/spec/version/version_spec.rb +3 -3
- data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
- metadata +54 -35
- data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +0 -31
- data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +0 -11
- data/spec/controllers/application_metal_controller.rb +0 -10
data/doorkeeper.gemspec
CHANGED
@@ -1,32 +1,31 @@
|
|
1
|
-
$LOAD_PATH.push File.expand_path(
|
1
|
+
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'doorkeeper/version'
|
4
4
|
|
5
|
-
Gem::Specification.new do |
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.name = 'doorkeeper'
|
7
|
+
gem.version = Doorkeeper.gem_version
|
8
|
+
gem.authors = ['Felipe Elias Philipp', 'Tute Costa', 'Jon Moss', 'Nikita Bulai']
|
9
|
+
gem.email = %w(bulaj.nikita@gmail.com)
|
10
|
+
gem.homepage = 'https://github.com/doorkeeper-gem/doorkeeper'
|
11
|
+
gem.summary = 'OAuth 2 provider for Rails and Grape'
|
12
|
+
gem.description = 'Doorkeeper is an OAuth 2 provider for Rails and Grape.'
|
13
|
+
gem.license = 'MIT'
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
gem.files = `git ls-files`.split("\n")
|
16
|
+
gem.test_files = `git ls-files -- spec/*`.split("\n")
|
17
|
+
gem.require_paths = ['lib']
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
gem.add_dependency 'railties', '>= 4.2'
|
20
|
+
gem.required_ruby_version = '>= 2.1'
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
s.post_install_message = Doorkeeper::CVE_2018_1000211_WARNING
|
22
|
+
gem.add_development_dependency 'capybara', '~> 2.18'
|
23
|
+
gem.add_development_dependency 'coveralls'
|
24
|
+
gem.add_development_dependency 'danger', '~> 5.0'
|
25
|
+
gem.add_development_dependency 'grape'
|
26
|
+
gem.add_development_dependency 'database_cleaner', '~> 1.6'
|
27
|
+
gem.add_development_dependency 'factory_bot', '~> 4.8'
|
28
|
+
gem.add_development_dependency 'generator_spec', '~> 0.9.3'
|
29
|
+
gem.add_development_dependency 'rake', '>= 11.3.0'
|
30
|
+
gem.add_development_dependency 'rspec-rails'
|
32
31
|
end
|
data/gemfiles/rails_5_2.gemfile
CHANGED
@@ -9,6 +9,9 @@ gem "appraisal"
|
|
9
9
|
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
|
10
10
|
gem "sqlite3", platform: [:ruby, :mswin, :mingw, :x64_mingw]
|
11
11
|
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw]
|
12
|
-
|
12
|
+
|
13
|
+
%w[rspec-core rspec-expectations rspec-mocks rspec-rails rspec-support].each do |lib|
|
14
|
+
gem lib, git: "https://github.com/rspec/#{lib}.git", branch: 'master'
|
15
|
+
end
|
13
16
|
|
14
17
|
gemspec path: "../"
|
data/lib/doorkeeper/config.rb
CHANGED
@@ -15,19 +15,19 @@ module Doorkeeper
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.configuration
|
18
|
-
@config || (
|
18
|
+
@config || (raise MissingConfiguration)
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.setup_orm_adapter
|
22
22
|
@orm_adapter = "doorkeeper/orm/#{configuration.orm}".classify.constantize
|
23
|
-
rescue NameError =>
|
24
|
-
|
25
|
-
[doorkeeper] ORM adapter not found (#{configuration.orm}), or there was an error
|
26
|
-
trying to load it.
|
27
|
-
|
28
|
-
You probably need to add the related gem for this adapter to work with
|
29
|
-
doorkeeper.
|
30
|
-
|
23
|
+
rescue NameError => error
|
24
|
+
raise error, "ORM adapter not found (#{configuration.orm})", <<-ERROR_MSG.strip_heredoc
|
25
|
+
[doorkeeper] ORM adapter not found (#{configuration.orm}), or there was an error
|
26
|
+
trying to load it.
|
27
|
+
|
28
|
+
You probably need to add the related gem for this adapter to work with
|
29
|
+
doorkeeper.
|
30
|
+
ERROR_MSG
|
31
31
|
end
|
32
32
|
|
33
33
|
def self.setup_orm_models
|
@@ -90,7 +90,7 @@ doorkeeper.
|
|
90
90
|
#
|
91
91
|
# @param methods [Array] Define client credentials
|
92
92
|
def client_credentials(*methods)
|
93
|
-
@config.instance_variable_set(:@
|
93
|
+
@config.instance_variable_set(:@client_credentials_methods, methods)
|
94
94
|
end
|
95
95
|
|
96
96
|
# Change the way access token is authenticated from the request object.
|
@@ -103,9 +103,12 @@ doorkeeper.
|
|
103
103
|
@config.instance_variable_set(:@access_token_methods, methods)
|
104
104
|
end
|
105
105
|
|
106
|
-
# Issue access tokens with refresh token (disabled
|
107
|
-
def use_refresh_token
|
108
|
-
@config.instance_variable_set(
|
106
|
+
# Issue access tokens with refresh token (disabled if not set)
|
107
|
+
def use_refresh_token(enabled = true, &block)
|
108
|
+
@config.instance_variable_set(
|
109
|
+
:@refresh_token_enabled,
|
110
|
+
block || enabled
|
111
|
+
)
|
109
112
|
end
|
110
113
|
|
111
114
|
# Reuse access token for the same resource owner within an application
|
@@ -115,13 +118,23 @@ doorkeeper.
|
|
115
118
|
@config.instance_variable_set(:@reuse_access_token, true)
|
116
119
|
end
|
117
120
|
|
118
|
-
#
|
119
|
-
#
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
121
|
+
# Use an API mode for applications generated with --api argument
|
122
|
+
# It will skip applications controller, disable forgery protection
|
123
|
+
def api_only
|
124
|
+
@config.instance_variable_set(:@api_only, true)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Forbids creating/updating applications with arbitrary scopes that are
|
128
|
+
# not in configuration, i.e. `default_scopes` or `optional_scopes`.
|
129
|
+
# (disabled by default)
|
130
|
+
def enforce_configured_scopes
|
131
|
+
@config.instance_variable_set(:@enforce_configured_scopes, true)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Enforce request content type as the spec requires:
|
135
|
+
# disabled by default for backward compatibility.
|
136
|
+
def enforce_content_type
|
137
|
+
@config.instance_variable_set(:@enforce_content_type, true)
|
125
138
|
end
|
126
139
|
end
|
127
140
|
|
@@ -164,7 +177,7 @@ doorkeeper.
|
|
164
177
|
value = if attribute_builder
|
165
178
|
attribute_builder.new(&block).build
|
166
179
|
else
|
167
|
-
block
|
180
|
+
block || args.first
|
168
181
|
end
|
169
182
|
|
170
183
|
@config.instance_variable_set(:"@#{attribute}", value)
|
@@ -188,30 +201,45 @@ doorkeeper.
|
|
188
201
|
option :resource_owner_authenticator,
|
189
202
|
as: :authenticate_resource_owner,
|
190
203
|
default: (lambda do |_routes|
|
191
|
-
::Rails.logger.warn(
|
204
|
+
::Rails.logger.warn(
|
205
|
+
I18n.t('doorkeeper.errors.messages.resource_owner_authenticator_not_configured')
|
206
|
+
)
|
207
|
+
|
192
208
|
nil
|
193
209
|
end)
|
194
210
|
|
195
211
|
option :admin_authenticator,
|
196
212
|
as: :authenticate_admin,
|
197
|
-
default:
|
213
|
+
default: (lambda do |_routes|
|
214
|
+
::Rails.logger.warn(
|
215
|
+
I18n.t('doorkeeper.errors.messages.admin_authenticator_not_configured')
|
216
|
+
)
|
217
|
+
|
218
|
+
head :forbidden
|
219
|
+
end)
|
198
220
|
|
199
221
|
option :resource_owner_from_credentials,
|
200
222
|
default: (lambda do |_routes|
|
201
|
-
::Rails.logger.warn(
|
223
|
+
::Rails.logger.warn(
|
224
|
+
I18n.t('doorkeeper.errors.messages.credential_flow_not_configured')
|
225
|
+
)
|
226
|
+
|
202
227
|
nil
|
203
228
|
end)
|
229
|
+
option :before_successful_authorization, default: ->(_context) {}
|
230
|
+
option :after_successful_authorization, default: ->(_context) {}
|
204
231
|
option :before_successful_strategy_response, default: ->(_request) {}
|
205
232
|
option :after_successful_strategy_response,
|
206
233
|
default: ->(_request, _response) {}
|
207
234
|
option :skip_authorization, default: ->(_routes) {}
|
208
235
|
option :access_token_expires_in, default: 7200
|
209
|
-
option :custom_access_token_expires_in, default: ->(
|
236
|
+
option :custom_access_token_expires_in, default: ->(_context) { nil }
|
210
237
|
option :authorization_code_expires_in, default: 600
|
211
238
|
option :orm, default: :active_record
|
212
239
|
option :native_redirect_uri, default: 'urn:ietf:wg:oauth:2.0:oob'
|
213
240
|
option :active_record_options, default: {}
|
214
241
|
option :grant_flows, default: %w[authorization_code client_credentials]
|
242
|
+
option :handle_auth_errors, default: :render
|
215
243
|
|
216
244
|
# Allows to forbid specific Application redirect URI's by custom rules.
|
217
245
|
# Doesn't forbid any URI by default.
|
@@ -241,7 +269,6 @@ doorkeeper.
|
|
241
269
|
#
|
242
270
|
option :force_ssl_in_redirect_uri, default: !Rails.env.development?
|
243
271
|
|
244
|
-
|
245
272
|
# Use a custom class for generating the access token.
|
246
273
|
# https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
|
247
274
|
#
|
@@ -260,20 +287,39 @@ doorkeeper.
|
|
260
287
|
default: 'ActionController::Base'
|
261
288
|
|
262
289
|
attr_reader :reuse_access_token
|
290
|
+
attr_reader :api_only
|
291
|
+
attr_reader :enforce_content_type
|
292
|
+
|
293
|
+
def api_only
|
294
|
+
@api_only ||= false
|
295
|
+
end
|
296
|
+
|
297
|
+
def enforce_content_type
|
298
|
+
@enforce_content_type ||= false
|
299
|
+
end
|
263
300
|
|
264
301
|
def refresh_token_enabled?
|
265
|
-
@refresh_token_enabled
|
266
|
-
|
302
|
+
if defined?(@refresh_token_enabled)
|
303
|
+
@refresh_token_enabled
|
304
|
+
else
|
305
|
+
false
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def enforce_configured_scopes?
|
310
|
+
!!(defined?(@enforce_configured_scopes) && @enforce_configured_scopes)
|
267
311
|
end
|
268
312
|
|
269
313
|
def enable_application_owner?
|
270
|
-
@enable_application_owner
|
271
|
-
!!@enable_application_owner
|
314
|
+
!!(defined?(@enable_application_owner) && @enable_application_owner)
|
272
315
|
end
|
273
316
|
|
274
317
|
def confirm_application_owner?
|
275
|
-
@confirm_application_owner
|
276
|
-
|
318
|
+
!!(defined?(@confirm_application_owner) && @confirm_application_owner)
|
319
|
+
end
|
320
|
+
|
321
|
+
def raise_on_errors?
|
322
|
+
handle_auth_errors == :raise
|
277
323
|
end
|
278
324
|
|
279
325
|
def default_scopes
|
@@ -289,7 +335,7 @@ doorkeeper.
|
|
289
335
|
end
|
290
336
|
|
291
337
|
def client_credentials_methods
|
292
|
-
@
|
338
|
+
@client_credentials_methods ||= %i[from_basic from_params]
|
293
339
|
end
|
294
340
|
|
295
341
|
def access_token_methods
|
@@ -297,16 +343,11 @@ doorkeeper.
|
|
297
343
|
end
|
298
344
|
|
299
345
|
def authorization_response_types
|
300
|
-
@authorization_response_types ||= calculate_authorization_response_types
|
346
|
+
@authorization_response_types ||= calculate_authorization_response_types.freeze
|
301
347
|
end
|
302
348
|
|
303
349
|
def token_grant_types
|
304
|
-
@token_grant_types ||= calculate_token_grant_types
|
305
|
-
end
|
306
|
-
|
307
|
-
def native_authorization_code_route
|
308
|
-
@opt_out_native_route_change ||= false
|
309
|
-
@opt_out_native_route_change ? '/:code' : '/native'
|
350
|
+
@token_grant_types ||= calculate_token_grant_types.freeze
|
310
351
|
end
|
311
352
|
|
312
353
|
private
|
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|
|
@@ -17,6 +19,10 @@ module Doorkeeper
|
|
17
19
|
|
18
20
|
if defined?(Sprockets) && Sprockets::VERSION.chr.to_i >= 4
|
19
21
|
initializer 'doorkeeper.assets.precompile' do |app|
|
22
|
+
# Force users to use:
|
23
|
+
# //= link doorkeeper/admin/application.css
|
24
|
+
# in Doorkeeper 5 for Sprockets 4 instead of precompile.
|
25
|
+
# Add note to official docs & Wiki
|
20
26
|
app.config.assets.precompile += %w[
|
21
27
|
doorkeeper/application.css
|
22
28
|
doorkeeper/admin/application.css
|
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,10 +38,22 @@ module Doorkeeper
|
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
39
|
-
class
|
40
|
-
|
41
|
+
class BaseResponseError < DoorkeeperError
|
42
|
+
attr_reader :response
|
41
43
|
|
42
|
-
|
44
|
+
def initialize(response)
|
45
|
+
@response = response
|
46
|
+
end
|
43
47
|
end
|
48
|
+
|
49
|
+
UnableToGenerateToken = Class.new(DoorkeeperError)
|
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
|
44
58
|
end
|
45
59
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'doorkeeper/grape/authorization_decorator'
|
2
4
|
|
3
5
|
module Doorkeeper
|
@@ -31,7 +33,7 @@ module Doorkeeper
|
|
31
33
|
end
|
32
34
|
|
33
35
|
def doorkeeper_token
|
34
|
-
@
|
36
|
+
@doorkeeper_token ||= OAuth::Token.authenticate(
|
35
37
|
decorated_request,
|
36
38
|
*Doorkeeper.configuration.access_token_methods
|
37
39
|
)
|
@@ -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
|
@@ -30,11 +32,11 @@ module Doorkeeper
|
|
30
32
|
|
31
33
|
# :doc:
|
32
34
|
def doorkeeper_token
|
33
|
-
@
|
35
|
+
@doorkeeper_token ||= OAuth::Token.authenticate request, *config_methods
|
34
36
|
end
|
35
37
|
|
36
38
|
def config_methods
|
37
|
-
@
|
39
|
+
@config_methods ||= Doorkeeper.configuration.access_token_methods
|
38
40
|
end
|
39
41
|
|
40
42
|
def get_error_response_from_exception(exception)
|
@@ -51,6 +53,11 @@ module Doorkeeper
|
|
51
53
|
def skip_authorization?
|
52
54
|
!!instance_exec([@server.current_resource_owner, @pre_auth.client], &Doorkeeper.configuration.skip_authorization)
|
53
55
|
end
|
56
|
+
|
57
|
+
def enforce_content_type
|
58
|
+
return if request.content_type == 'application/x-www-form-urlencoded'
|
59
|
+
render json: {}, status: :unsupported_media_type
|
60
|
+
end
|
54
61
|
end
|
55
62
|
end
|
56
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
|
@@ -9,6 +11,15 @@ module Doorkeeper
|
|
9
11
|
include Models::Orderable
|
10
12
|
include Models::Scopes
|
11
13
|
|
14
|
+
# never uses pkce, if pkce migrations were not generated
|
15
|
+
def uses_pkce?
|
16
|
+
pkce_supported? && code_challenge.present?
|
17
|
+
end
|
18
|
+
|
19
|
+
def pkce_supported?
|
20
|
+
respond_to? :code_challenge
|
21
|
+
end
|
22
|
+
|
12
23
|
module ClassMethods
|
13
24
|
# Searches for Doorkeeper::AccessGrant record with the
|
14
25
|
# specific token value.
|
@@ -21,6 +32,68 @@ module Doorkeeper
|
|
21
32
|
def by_token(token)
|
22
33
|
find_by(token: token.to_s)
|
23
34
|
end
|
35
|
+
|
36
|
+
# Revokes AccessGrant records that have not been revoked and associated
|
37
|
+
# with the specific Application and Resource Owner.
|
38
|
+
#
|
39
|
+
# @param application_id [Integer]
|
40
|
+
# ID of the Application
|
41
|
+
# @param resource_owner [ActiveRecord::Base]
|
42
|
+
# instance of the Resource Owner model
|
43
|
+
#
|
44
|
+
def revoke_all_for(application_id, resource_owner, clock = Time)
|
45
|
+
where(application_id: application_id,
|
46
|
+
resource_owner_id: resource_owner.id,
|
47
|
+
revoked_at: nil)
|
48
|
+
.update_all(revoked_at: clock.now.utc)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Implements PKCE code_challenge encoding without base64 padding as described in the spec.
|
52
|
+
# https://tools.ietf.org/html/rfc7636#appendix-A
|
53
|
+
# Appendix A. Notes on Implementing Base64url Encoding without Padding
|
54
|
+
#
|
55
|
+
# This appendix describes how to implement a base64url-encoding
|
56
|
+
# function without padding, based upon the standard base64-encoding
|
57
|
+
# function that uses padding.
|
58
|
+
#
|
59
|
+
# To be concrete, example C# code implementing these functions is shown
|
60
|
+
# below. Similar code could be used in other languages.
|
61
|
+
#
|
62
|
+
# static string base64urlencode(byte [] arg)
|
63
|
+
# {
|
64
|
+
# string s = Convert.ToBase64String(arg); // Regular base64 encoder
|
65
|
+
# s = s.Split('=')[0]; // Remove any trailing '='s
|
66
|
+
# s = s.Replace('+', '-'); // 62nd char of encoding
|
67
|
+
# s = s.Replace('/', '_'); // 63rd char of encoding
|
68
|
+
# return s;
|
69
|
+
# }
|
70
|
+
#
|
71
|
+
# An example correspondence between unencoded and encoded values
|
72
|
+
# follows. The octet sequence below encodes into the string below,
|
73
|
+
# which when decoded, reproduces the octet sequence.
|
74
|
+
#
|
75
|
+
# 3 236 255 224 193
|
76
|
+
#
|
77
|
+
# A-z_4ME
|
78
|
+
#
|
79
|
+
# https://ruby-doc.org/stdlib-2.1.3/libdoc/base64/rdoc/Base64.html#method-i-urlsafe_encode64
|
80
|
+
#
|
81
|
+
# urlsafe_encode64(bin)
|
82
|
+
# Returns the Base64-encoded version of bin. This method complies with
|
83
|
+
# "Base 64 Encoding with URL and Filename Safe Alphabet" in RFC 4648.
|
84
|
+
# The alphabet uses '-' instead of '+' and '_' instead of '/'.
|
85
|
+
|
86
|
+
# @param code_verifier [#to_s] a one time use value (any object that responds to `#to_s`)
|
87
|
+
#
|
88
|
+
# @return [#to_s] An encoded code challenge based on the provided verifier suitable for PKCE validation
|
89
|
+
def generate_code_challenge(code_verifier)
|
90
|
+
padded_result = Base64.urlsafe_encode64(Digest::SHA256.digest(code_verifier))
|
91
|
+
padded_result.split('=')[0] # Remove any trailing '='
|
92
|
+
end
|
93
|
+
|
94
|
+
def pkce_supported?
|
95
|
+
new.pkce_supported?
|
96
|
+
end
|
24
97
|
end
|
25
98
|
end
|
26
99
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module AccessTokenMixin
|
3
5
|
extend ActiveSupport::Concern
|
@@ -47,11 +49,11 @@ module Doorkeeper
|
|
47
49
|
def revoke_all_for(application_id, resource_owner, clock = Time)
|
48
50
|
where(application_id: application_id,
|
49
51
|
resource_owner_id: resource_owner.id,
|
50
|
-
revoked_at: nil)
|
51
|
-
update_all(revoked_at: clock.now.utc)
|
52
|
+
revoked_at: nil)
|
53
|
+
.update_all(revoked_at: clock.now.utc)
|
52
54
|
end
|
53
55
|
|
54
|
-
# Looking for not
|
56
|
+
# Looking for not revoked Access Token with a matching set of scopes
|
55
57
|
# that belongs to specific Application and Resource Owner.
|
56
58
|
#
|
57
59
|
# @param application [Doorkeeper::Application]
|
@@ -70,30 +72,34 @@ module Doorkeeper
|
|
70
72
|
else
|
71
73
|
resource_owner_or_id
|
72
74
|
end
|
73
|
-
|
74
|
-
|
75
|
-
|
75
|
+
|
76
|
+
tokens = authorized_tokens_for(application.try(:id), resource_owner_id)
|
77
|
+
tokens.detect do |token|
|
78
|
+
scopes_match?(token.scopes, scopes, application.try(:scopes))
|
76
79
|
end
|
77
80
|
end
|
78
81
|
|
79
|
-
# Checks whether the token scopes match the scopes from the parameters
|
80
|
-
# Application scopes (if present).
|
82
|
+
# Checks whether the token scopes match the scopes from the parameters
|
81
83
|
#
|
82
84
|
# @param token_scopes [#to_s]
|
83
85
|
# set of scopes (any object that responds to `#to_s`)
|
84
|
-
# @param param_scopes [
|
86
|
+
# @param param_scopes [Doorkeeper::OAuth::Scopes]
|
85
87
|
# scopes from params
|
86
|
-
# @param app_scopes [
|
88
|
+
# @param app_scopes [Doorkeeper::OAuth::Scopes]
|
87
89
|
# Application scopes
|
88
90
|
#
|
89
|
-
# @return [Boolean] true if
|
91
|
+
# @return [Boolean] true if the param scopes match the token scopes,
|
92
|
+
# and all the param scopes are defined in the application (or in the
|
93
|
+
# server configuration if the application doesn't define any scopes),
|
90
94
|
# and false in other cases
|
91
95
|
#
|
92
96
|
def scopes_match?(token_scopes, param_scopes, app_scopes)
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
+
return true if token_scopes.empty? && param_scopes.empty?
|
98
|
+
|
99
|
+
(token_scopes.sort == param_scopes.sort) &&
|
100
|
+
Doorkeeper::OAuth::Helpers::ScopeChecker.valid?(
|
101
|
+
param_scopes.to_s,
|
102
|
+
Doorkeeper.configuration.scopes,
|
97
103
|
app_scopes
|
98
104
|
)
|
99
105
|
end
|
@@ -118,9 +124,8 @@ module Doorkeeper
|
|
118
124
|
def find_or_create_for(application, resource_owner_id, scopes, expires_in, use_refresh_token)
|
119
125
|
if Doorkeeper.configuration.reuse_access_token
|
120
126
|
access_token = matching_token_for(application, resource_owner_id, scopes)
|
121
|
-
|
122
|
-
|
123
|
-
end
|
127
|
+
|
128
|
+
return access_token if access_token && !access_token.expired?
|
124
129
|
end
|
125
130
|
|
126
131
|
create!(
|
@@ -132,7 +137,7 @@ module Doorkeeper
|
|
132
137
|
)
|
133
138
|
end
|
134
139
|
|
135
|
-
# Looking for not revoked Access Token
|
140
|
+
# Looking for not revoked Access Token records that belongs to specific
|
136
141
|
# Application and Resource Owner.
|
137
142
|
#
|
138
143
|
# @param application_id [Integer]
|
@@ -140,14 +145,28 @@ module Doorkeeper
|
|
140
145
|
# @param resource_owner_id [Integer]
|
141
146
|
# ID of the Resource Owner model instance
|
142
147
|
#
|
148
|
+
# @return [Doorkeeper::AccessToken] array of matching AccessToken objects
|
149
|
+
#
|
150
|
+
def authorized_tokens_for(application_id, resource_owner_id)
|
151
|
+
ordered_by(:created_at, :desc)
|
152
|
+
.where(application_id: application_id,
|
153
|
+
resource_owner_id: resource_owner_id,
|
154
|
+
revoked_at: nil)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Convenience method for backwards-compatibility, return the last
|
158
|
+
# matching token for the given Application and Resource Owner.
|
159
|
+
#
|
160
|
+
# @param application_id [Integer]
|
161
|
+
# ID of the Application model instance
|
162
|
+
# @param resource_owner_id [Integer]
|
163
|
+
# ID of the Resource Owner model instance
|
164
|
+
#
|
143
165
|
# @return [Doorkeeper::AccessToken, nil] matching AccessToken object or
|
144
166
|
# nil if nothing was found
|
145
167
|
#
|
146
168
|
def last_authorized_token_for(application_id, resource_owner_id)
|
147
|
-
|
148
|
-
find_by(application_id: application_id,
|
149
|
-
resource_owner_id: resource_owner_id,
|
150
|
-
revoked_at: nil)
|
169
|
+
authorized_tokens_for(application_id, resource_owner_id).first
|
151
170
|
end
|
152
171
|
end
|
153
172
|
|
@@ -170,8 +189,8 @@ module Doorkeeper
|
|
170
189
|
def as_json(_options = {})
|
171
190
|
{
|
172
191
|
resource_owner_id: resource_owner_id,
|
173
|
-
|
174
|
-
|
192
|
+
scope: scopes,
|
193
|
+
expires_in: expires_in_seconds,
|
175
194
|
application: { uid: application.try(:uid) },
|
176
195
|
created_at: created_at.to_i
|
177
196
|
}
|