doorkeeper 4.2.6 → 5.0.0.rc1
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 +4 -4
- data/.github/ISSUE_TEMPLATE.md +25 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
- data/.gitignore +2 -1
- data/.hound.yml +2 -13
- data/.rubocop.yml +17 -0
- data/.travis.yml +19 -5
- data/Appraisals +8 -4
- data/CODE_OF_CONDUCT.md +46 -0
- data/Gemfile +1 -1
- data/NEWS.md +77 -0
- data/README.md +169 -34
- data/Rakefile +6 -0
- data/SECURITY.md +15 -0
- data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +2 -5
- data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
- data/app/controllers/doorkeeper/applications_controller.rb +47 -13
- data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +15 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +15 -7
- data/app/helpers/doorkeeper/dashboard_helper.rb +8 -6
- data/app/validators/redirect_uri_validator.rb +13 -2
- data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
- data/app/views/doorkeeper/applications/_form.html.erb +31 -19
- data/app/views/doorkeeper/applications/edit.html.erb +1 -1
- data/app/views/doorkeeper/applications/index.html.erb +18 -6
- data/app/views/doorkeeper/applications/new.html.erb +1 -1
- data/app/views/doorkeeper/applications/show.html.erb +8 -5
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
- data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
- data/config/locales/en.yml +18 -6
- data/doorkeeper.gemspec +6 -5
- data/gemfiles/rails_4_2.gemfile +6 -4
- data/gemfiles/rails_5_0.gemfile +4 -4
- data/gemfiles/rails_5_1.gemfile +6 -7
- data/gemfiles/rails_5_2.gemfile +12 -0
- data/gemfiles/rails_master.gemfile +14 -0
- data/lib/doorkeeper/config.rb +107 -68
- data/lib/doorkeeper/engine.rb +7 -3
- data/lib/doorkeeper/errors.rb +2 -5
- data/lib/doorkeeper/grape/helpers.rb +14 -9
- data/lib/doorkeeper/helpers/controller.rb +15 -6
- data/lib/doorkeeper/models/access_grant_mixin.rb +52 -23
- data/lib/doorkeeper/models/access_token_mixin.rb +51 -52
- data/lib/doorkeeper/models/application_mixin.rb +16 -30
- data/lib/doorkeeper/models/concerns/expirable.rb +7 -5
- data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
- data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/code.rb +31 -8
- data/lib/doorkeeper/oauth/authorization/context.rb +15 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +41 -20
- data/lib/doorkeeper/oauth/authorization_code_request.rb +33 -3
- data/lib/doorkeeper/oauth/base_request.rb +22 -7
- data/lib/doorkeeper/oauth/client/credentials.rb +6 -4
- data/lib/doorkeeper/oauth/client.rb +2 -2
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -1
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -2
- data/lib/doorkeeper/oauth/error.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +11 -4
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +15 -0
- data/lib/doorkeeper/oauth/invalid_token_response.rb +3 -4
- data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -4
- data/lib/doorkeeper/oauth/pre_authorization.rb +45 -13
- data/lib/doorkeeper/oauth/refresh_token_request.rb +7 -1
- data/lib/doorkeeper/oauth/scopes.rb +19 -9
- data/lib/doorkeeper/oauth/token.rb +6 -3
- data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
- data/lib/doorkeeper/oauth/token_response.rb +4 -2
- data/lib/doorkeeper/oauth.rb +13 -0
- data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
- data/lib/doorkeeper/orm/active_record/access_token.rb +21 -20
- data/lib/doorkeeper/orm/active_record/application.rb +34 -0
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
- data/lib/doorkeeper/orm/active_record.rb +21 -8
- data/lib/doorkeeper/rails/helpers.rb +7 -10
- data/lib/doorkeeper/rails/routes.rb +21 -7
- 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/password.rb +1 -11
- data/lib/doorkeeper/request.rb +29 -23
- data/lib/doorkeeper/validations.rb +3 -2
- data/lib/doorkeeper/version.rb +14 -1
- data/lib/doorkeeper.rb +6 -17
- data/lib/generators/doorkeeper/application_owner_generator.rb +26 -12
- 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 +26 -9
- data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +31 -20
- data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
- data/lib/generators/doorkeeper/templates/{add_owner_to_application_migration.rb → add_owner_to_application_migration.rb.erb} +1 -1
- data/lib/generators/doorkeeper/templates/{add_previous_refresh_token_to_access_tokens.rb → add_previous_refresh_token_to_access_tokens.rb.erb} +1 -1
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +88 -10
- data/lib/generators/doorkeeper/templates/{migration.rb → migration.rb.erb} +2 -1
- 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 +141 -17
- data/spec/controllers/authorizations_controller_spec.rb +255 -20
- data/spec/controllers/protected_resources_controller_spec.rb +44 -35
- data/spec/controllers/token_info_controller_spec.rb +17 -21
- data/spec/controllers/tokens_controller_spec.rb +142 -10
- data/spec/dummy/app/assets/config/manifest.js +2 -0
- data/spec/dummy/config/environments/test.rb +4 -5
- data/spec/dummy/config/initializers/doorkeeper.rb +18 -1
- data/spec/dummy/config/initializers/{active_record_belongs_to_required_by_default.rb → new_framework_defaults.rb} +5 -1
- data/spec/dummy/config/initializers/secret_token.rb +0 -1
- data/spec/dummy/config/routes.rb +3 -42
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -1
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +3 -1
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +3 -1
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +13 -0
- data/spec/dummy/db/schema.rb +38 -37
- data/spec/factories.rb +1 -1
- data/spec/generators/application_owner_generator_spec.rb +25 -6
- data/spec/generators/confidential_applications_generator_spec.rb +45 -0
- data/spec/generators/install_generator_spec.rb +1 -1
- data/spec/generators/migration_generator_spec.rb +25 -4
- data/spec/generators/pkce_generator_spec.rb +43 -0
- data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
- data/spec/generators/views_generator_spec.rb +1 -1
- data/spec/grape/grape_integration_spec.rb +135 -0
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +2 -2
- data/spec/lib/config_spec.rb +170 -22
- data/spec/lib/doorkeeper_spec.rb +1 -126
- data/spec/lib/models/expirable_spec.rb +0 -3
- data/spec/lib/models/revocable_spec.rb +2 -4
- 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 +63 -13
- data/spec/lib/oauth/base_request_spec.rb +19 -10
- data/spec/lib/oauth/base_response_spec.rb +1 -1
- data/spec/lib/oauth/client/credentials_spec.rb +5 -5
- data/spec/lib/oauth/client_credentials/creator_spec.rb +6 -2
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +26 -7
- data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -3
- data/spec/lib/oauth/client_credentials_integration_spec.rb +2 -2
- data/spec/lib/oauth/client_credentials_request_spec.rb +4 -5
- data/spec/lib/oauth/client_spec.rb +0 -3
- data/spec/lib/oauth/code_request_spec.rb +5 -5
- data/spec/lib/oauth/error_response_spec.rb +0 -3
- data/spec/lib/oauth/error_spec.rb +1 -3
- data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -3
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -3
- data/spec/lib/oauth/invalid_token_response_spec.rb +2 -5
- data/spec/lib/oauth/password_access_token_request_spec.rb +46 -5
- data/spec/lib/oauth/pre_authorization_spec.rb +40 -6
- data/spec/lib/oauth/refresh_token_request_spec.rb +30 -14
- data/spec/lib/oauth/scopes_spec.rb +28 -4
- data/spec/lib/oauth/token_request_spec.rb +10 -13
- data/spec/lib/oauth/token_response_spec.rb +0 -1
- data/spec/lib/oauth/token_spec.rb +37 -14
- data/spec/lib/orm/active_record/stale_records_cleaner_spec.rb +79 -0
- data/spec/lib/request/strategy_spec.rb +0 -1
- data/spec/lib/server_spec.rb +10 -0
- data/spec/models/doorkeeper/access_grant_spec.rb +2 -2
- data/spec/models/doorkeeper/access_token_spec.rb +118 -60
- data/spec/models/doorkeeper/application_spec.rb +101 -23
- data/spec/requests/applications/applications_request_spec.rb +94 -6
- data/spec/requests/applications/authorized_applications_spec.rb +1 -1
- data/spec/requests/endpoints/authorization_spec.rb +1 -1
- data/spec/requests/endpoints/token_spec.rb +15 -6
- data/spec/requests/flows/authorization_code_errors_spec.rb +1 -1
- data/spec/requests/flows/authorization_code_spec.rb +198 -1
- data/spec/requests/flows/client_credentials_spec.rb +73 -5
- 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 +160 -24
- data/spec/requests/flows/refresh_token_spec.rb +6 -6
- data/spec/requests/flows/revoke_token_spec.rb +26 -26
- data/spec/requests/flows/skip_authorization_spec.rb +16 -11
- data/spec/requests/protected_resources/metal_spec.rb +2 -2
- data/spec/requests/protected_resources/private_api_spec.rb +2 -2
- data/spec/routing/custom_controller_routes_spec.rb +63 -7
- data/spec/routing/default_routes_spec.rb +6 -2
- data/spec/routing/scoped_routes_spec.rb +16 -2
- data/spec/spec_helper.rb +54 -3
- data/spec/spec_helper_integration.rb +2 -63
- data/spec/support/dependencies/factory_bot.rb +2 -0
- data/spec/support/doorkeeper_rspec.rb +19 -0
- data/spec/support/helpers/access_token_request_helper.rb +1 -1
- data/spec/support/helpers/authorization_request_helper.rb +4 -4
- data/spec/support/helpers/model_helper.rb +9 -4
- data/spec/support/helpers/request_spec_helper.rb +10 -6
- data/spec/support/helpers/url_helper.rb +15 -10
- data/spec/support/http_method_shim.rb +12 -16
- data/spec/support/shared/controllers_shared_context.rb +2 -6
- data/spec/support/shared/models_shared_examples.rb +4 -4
- data/spec/validators/redirect_uri_validator_spec.rb +58 -7
- data/spec/version/version_spec.rb +15 -0
- data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
- metadata +73 -19
- data/spec/controllers/application_metal_controller.rb +0 -10
- data/spec/support/dependencies/factory_girl.rb +0 -2
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
|
|
@@ -59,12 +59,12 @@ doorkeeper.
|
|
|
59
59
|
# @option opts[Boolean] :confirmation (false)
|
|
60
60
|
# Set confirm_application_owner variable
|
|
61
61
|
def enable_application_owner(opts = {})
|
|
62
|
-
@config.instance_variable_set(
|
|
62
|
+
@config.instance_variable_set(:@enable_application_owner, true)
|
|
63
63
|
confirm_application_owner if opts[:confirmation].present? && opts[:confirmation]
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
def confirm_application_owner
|
|
67
|
-
@config.instance_variable_set(
|
|
67
|
+
@config.instance_variable_set(:@confirm_application_owner, true)
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
# Define default access token scopes for your provider
|
|
@@ -72,7 +72,7 @@ doorkeeper.
|
|
|
72
72
|
# @param scopes [Array] Default set of access (OAuth::Scopes.new)
|
|
73
73
|
# token scopes
|
|
74
74
|
def default_scopes(*scopes)
|
|
75
|
-
@config.instance_variable_set(
|
|
75
|
+
@config.instance_variable_set(:@default_scopes, OAuth::Scopes.from_array(scopes))
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
# Define default access token scopes for your provider
|
|
@@ -80,7 +80,7 @@ doorkeeper.
|
|
|
80
80
|
# @param scopes [Array] Optional set of access (OAuth::Scopes.new)
|
|
81
81
|
# token scopes
|
|
82
82
|
def optional_scopes(*scopes)
|
|
83
|
-
@config.instance_variable_set(
|
|
83
|
+
@config.instance_variable_set(:@optional_scopes, OAuth::Scopes.from_array(scopes))
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
# Change the way client credentials are retrieved from the request object.
|
|
@@ -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.
|
|
@@ -100,57 +100,38 @@ doorkeeper.
|
|
|
100
100
|
#
|
|
101
101
|
# @param methods [Array] Define access token methods
|
|
102
102
|
def access_token_methods(*methods)
|
|
103
|
-
@config.instance_variable_set(
|
|
103
|
+
@config.instance_variable_set(:@access_token_methods, methods)
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
# Issue access tokens with refresh token (disabled by default)
|
|
107
107
|
def use_refresh_token
|
|
108
|
-
@config.instance_variable_set(
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
# WWW-Authenticate Realm (default "Doorkeeper").
|
|
112
|
-
#
|
|
113
|
-
# @param realm [String] ("Doorkeeper") Authentication realm
|
|
114
|
-
def realm(realm)
|
|
115
|
-
@config.instance_variable_set('@realm', realm)
|
|
108
|
+
@config.instance_variable_set(:@refresh_token_enabled, true)
|
|
116
109
|
end
|
|
117
110
|
|
|
118
111
|
# Reuse access token for the same resource owner within an application
|
|
119
112
|
# (disabled by default)
|
|
120
113
|
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
|
|
121
114
|
def reuse_access_token
|
|
122
|
-
@config.instance_variable_set(
|
|
115
|
+
@config.instance_variable_set(:@reuse_access_token, true)
|
|
123
116
|
end
|
|
124
117
|
|
|
125
|
-
#
|
|
126
|
-
#
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
#
|
|
130
|
-
# @param [Boolean] boolean value for the parameter, true by default in
|
|
131
|
-
# non-development environment
|
|
132
|
-
def force_ssl_in_redirect_uri(boolean)
|
|
133
|
-
@config.instance_variable_set("@force_ssl_in_redirect_uri", boolean)
|
|
118
|
+
# Use an API mode for applications generated with --api argument
|
|
119
|
+
# It will skip applications controller, disable forgery protection
|
|
120
|
+
def api_only
|
|
121
|
+
@config.instance_variable_set(:@api_only, true)
|
|
134
122
|
end
|
|
135
123
|
|
|
136
|
-
#
|
|
137
|
-
#
|
|
138
|
-
#
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
def access_token_generator(access_token_generator)
|
|
142
|
-
@config.instance_variable_set(
|
|
143
|
-
'@access_token_generator', access_token_generator
|
|
144
|
-
)
|
|
124
|
+
# Forbids creating/updating applications with arbitrary scopes that are
|
|
125
|
+
# not in configuration, i.e. `default_scopes` or `optional_scopes`.
|
|
126
|
+
# (disabled by default)
|
|
127
|
+
def enforce_configured_scopes
|
|
128
|
+
@config.instance_variable_set(:@enforce_configured_scopes, true)
|
|
145
129
|
end
|
|
146
130
|
|
|
147
|
-
#
|
|
148
|
-
#
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
# @param base_controller [String] the name of the base controller
|
|
152
|
-
def base_controller(base_controller)
|
|
153
|
-
@config.instance_variable_set('@base_controller', base_controller)
|
|
131
|
+
# Enforce request content type as the spec requires:
|
|
132
|
+
# disabled by default for backward compatibility.
|
|
133
|
+
def enforce_content_type
|
|
134
|
+
@config.instance_variable_set(:@enforce_content_type, true)
|
|
154
135
|
end
|
|
155
136
|
end
|
|
156
137
|
|
|
@@ -210,10 +191,6 @@ doorkeeper.
|
|
|
210
191
|
|
|
211
192
|
public attribute
|
|
212
193
|
end
|
|
213
|
-
|
|
214
|
-
def extended(base)
|
|
215
|
-
base.send(:private, :option)
|
|
216
|
-
end
|
|
217
194
|
end
|
|
218
195
|
|
|
219
196
|
extend Option
|
|
@@ -221,48 +198,110 @@ doorkeeper.
|
|
|
221
198
|
option :resource_owner_authenticator,
|
|
222
199
|
as: :authenticate_resource_owner,
|
|
223
200
|
default: (lambda do |_routes|
|
|
224
|
-
logger.warn(
|
|
201
|
+
::Rails.logger.warn(
|
|
202
|
+
I18n.t('doorkeeper.errors.messages.resource_owner_authenticator_not_configured')
|
|
203
|
+
)
|
|
204
|
+
|
|
225
205
|
nil
|
|
226
206
|
end)
|
|
207
|
+
|
|
227
208
|
option :admin_authenticator,
|
|
228
209
|
as: :authenticate_admin,
|
|
229
210
|
default: ->(_routes) {}
|
|
211
|
+
|
|
230
212
|
option :resource_owner_from_credentials,
|
|
231
213
|
default: (lambda do |_routes|
|
|
232
|
-
warn(
|
|
214
|
+
::Rails.logger.warn(
|
|
215
|
+
I18n.t('doorkeeper.errors.messages.credential_flow_not_configured')
|
|
216
|
+
)
|
|
217
|
+
|
|
233
218
|
nil
|
|
234
219
|
end)
|
|
235
|
-
|
|
220
|
+
option :before_successful_authorization, default: ->(_context) {}
|
|
221
|
+
option :after_successful_authorization, default: ->(_context) {}
|
|
222
|
+
option :before_successful_strategy_response, default: ->(_request) {}
|
|
223
|
+
option :after_successful_strategy_response,
|
|
224
|
+
default: ->(_request, _response) {}
|
|
236
225
|
option :skip_authorization, default: ->(_routes) {}
|
|
237
226
|
option :access_token_expires_in, default: 7200
|
|
238
|
-
option :custom_access_token_expires_in, default: ->(
|
|
227
|
+
option :custom_access_token_expires_in, default: ->(_context) { nil }
|
|
239
228
|
option :authorization_code_expires_in, default: 600
|
|
240
229
|
option :orm, default: :active_record
|
|
241
230
|
option :native_redirect_uri, default: 'urn:ietf:wg:oauth:2.0:oob'
|
|
242
231
|
option :active_record_options, default: {}
|
|
232
|
+
option :grant_flows, default: %w[authorization_code client_credentials]
|
|
233
|
+
|
|
234
|
+
# Allows to forbid specific Application redirect URI's by custom rules.
|
|
235
|
+
# Doesn't forbid any URI by default.
|
|
236
|
+
#
|
|
237
|
+
# @param forbid_redirect_uri [Proc] Block or any object respond to #call
|
|
238
|
+
#
|
|
239
|
+
option :forbid_redirect_uri, default: ->(_uri) { false }
|
|
240
|
+
|
|
241
|
+
# WWW-Authenticate Realm (default "Doorkeeper").
|
|
242
|
+
#
|
|
243
|
+
# @param realm [String] ("Doorkeeper") Authentication realm
|
|
244
|
+
#
|
|
243
245
|
option :realm, default: 'Doorkeeper'
|
|
246
|
+
|
|
247
|
+
# Forces the usage of the HTTPS protocol in non-native redirect uris
|
|
248
|
+
# (enabled by default in non-development environments). OAuth2
|
|
249
|
+
# delegates security in communication to the HTTPS protocol so it is
|
|
250
|
+
# wise to keep this enabled.
|
|
251
|
+
#
|
|
252
|
+
# @param [Boolean] boolean_or_block value for the parameter, true by default in
|
|
253
|
+
# non-development environment
|
|
254
|
+
#
|
|
255
|
+
# @yield [uri] Conditional usage of SSL redirect uris.
|
|
256
|
+
# @yieldparam [URI] Redirect URI
|
|
257
|
+
# @yieldreturn [Boolean] Indicates necessity of usage of the HTTPS protocol
|
|
258
|
+
# in non-native redirect uris
|
|
259
|
+
#
|
|
244
260
|
option :force_ssl_in_redirect_uri, default: !Rails.env.development?
|
|
245
|
-
|
|
261
|
+
|
|
262
|
+
# Use a custom class for generating the access token.
|
|
263
|
+
# https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
|
|
264
|
+
#
|
|
265
|
+
# @param access_token_generator [String]
|
|
266
|
+
# the name of the access token generator class
|
|
267
|
+
#
|
|
246
268
|
option :access_token_generator,
|
|
247
269
|
default: 'Doorkeeper::OAuth::Helpers::UniqueToken'
|
|
270
|
+
|
|
271
|
+
# The controller Doorkeeper::ApplicationController inherits from.
|
|
272
|
+
# Defaults to ActionController::Base.
|
|
273
|
+
# https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
|
|
274
|
+
#
|
|
275
|
+
# @param base_controller [String] the name of the base controller
|
|
248
276
|
option :base_controller,
|
|
249
277
|
default: 'ActionController::Base'
|
|
250
278
|
|
|
251
279
|
attr_reader :reuse_access_token
|
|
280
|
+
attr_reader :api_only
|
|
281
|
+
attr_reader :enforce_content_type
|
|
282
|
+
|
|
283
|
+
def api_only
|
|
284
|
+
@api_only ||= false
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def enforce_content_type
|
|
288
|
+
@enforce_content_type ||= false
|
|
289
|
+
end
|
|
252
290
|
|
|
253
291
|
def refresh_token_enabled?
|
|
254
|
-
@refresh_token_enabled
|
|
255
|
-
|
|
292
|
+
!!(defined?(@refresh_token_enabled) && @refresh_token_enabled)
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def enforce_configured_scopes?
|
|
296
|
+
!!(defined?(@enforce_configured_scopes) && @enforce_configured_scopes)
|
|
256
297
|
end
|
|
257
298
|
|
|
258
299
|
def enable_application_owner?
|
|
259
|
-
@enable_application_owner
|
|
260
|
-
!!@enable_application_owner
|
|
300
|
+
!!(defined?(@enable_application_owner) && @enable_application_owner)
|
|
261
301
|
end
|
|
262
302
|
|
|
263
303
|
def confirm_application_owner?
|
|
264
|
-
@confirm_application_owner
|
|
265
|
-
!!@confirm_application_owner
|
|
304
|
+
!!(defined?(@confirm_application_owner) && @confirm_application_owner)
|
|
266
305
|
end
|
|
267
306
|
|
|
268
307
|
def default_scopes
|
|
@@ -278,19 +317,19 @@ doorkeeper.
|
|
|
278
317
|
end
|
|
279
318
|
|
|
280
319
|
def client_credentials_methods
|
|
281
|
-
@
|
|
320
|
+
@client_credentials_methods ||= %i[from_basic from_params]
|
|
282
321
|
end
|
|
283
322
|
|
|
284
323
|
def access_token_methods
|
|
285
|
-
@access_token_methods ||= [
|
|
324
|
+
@access_token_methods ||= %i[from_bearer_authorization from_access_token_param from_bearer_param]
|
|
286
325
|
end
|
|
287
326
|
|
|
288
327
|
def authorization_response_types
|
|
289
|
-
@authorization_response_types ||= calculate_authorization_response_types
|
|
328
|
+
@authorization_response_types ||= calculate_authorization_response_types.freeze
|
|
290
329
|
end
|
|
291
330
|
|
|
292
331
|
def token_grant_types
|
|
293
|
-
@token_grant_types ||= calculate_token_grant_types
|
|
332
|
+
@token_grant_types ||= calculate_token_grant_types.freeze
|
|
294
333
|
end
|
|
295
334
|
|
|
296
335
|
private
|
data/lib/doorkeeper/engine.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Doorkeeper
|
|
2
2
|
class Engine < Rails::Engine
|
|
3
3
|
initializer "doorkeeper.params.filter" do |app|
|
|
4
|
-
parameters = %w
|
|
4
|
+
parameters = %w[client_secret code authentication_token access_token refresh_token]
|
|
5
5
|
app.config.filter_parameters << /^(#{Regexp.union parameters})$/
|
|
6
6
|
end
|
|
7
7
|
|
|
@@ -17,10 +17,14 @@ module Doorkeeper
|
|
|
17
17
|
|
|
18
18
|
if defined?(Sprockets) && Sprockets::VERSION.chr.to_i >= 4
|
|
19
19
|
initializer 'doorkeeper.assets.precompile' do |app|
|
|
20
|
-
|
|
20
|
+
# Force users to use:
|
|
21
|
+
# //= link doorkeeper/admin/application.css
|
|
22
|
+
# in Doorkeeper 5 for Sprockets 4 instead of precompile.
|
|
23
|
+
# Add note to official docs & Wiki
|
|
24
|
+
app.config.assets.precompile += %w[
|
|
21
25
|
doorkeeper/application.css
|
|
22
26
|
doorkeeper/admin/application.css
|
|
23
|
-
|
|
27
|
+
]
|
|
24
28
|
end
|
|
25
29
|
end
|
|
26
30
|
end
|
data/lib/doorkeeper/errors.rb
CHANGED
|
@@ -36,10 +36,7 @@ module Doorkeeper
|
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class TokenGeneratorNotFound < DoorkeeperError
|
|
43
|
-
end
|
|
39
|
+
UnableToGenerateToken = Class.new(DoorkeeperError)
|
|
40
|
+
TokenGeneratorNotFound = Class.new(DoorkeeperError)
|
|
44
41
|
end
|
|
45
42
|
end
|
|
@@ -9,7 +9,7 @@ module Doorkeeper
|
|
|
9
9
|
|
|
10
10
|
# endpoint specific scopes > parameter scopes > default scopes
|
|
11
11
|
def doorkeeper_authorize!(*scopes)
|
|
12
|
-
endpoint_scopes =
|
|
12
|
+
endpoint_scopes = endpoint.route_setting(:scopes) || endpoint.options[:route_options][:scopes]
|
|
13
13
|
scopes = if endpoint_scopes
|
|
14
14
|
Doorkeeper::OAuth::Scopes.from_array(endpoint_scopes)
|
|
15
15
|
elsif scopes && !scopes.empty?
|
|
@@ -20,20 +20,18 @@ module Doorkeeper
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def doorkeeper_render_error_with(error)
|
|
23
|
-
status_code =
|
|
24
|
-
when :unauthorized
|
|
25
|
-
401
|
|
26
|
-
when :forbidden
|
|
27
|
-
403
|
|
28
|
-
end
|
|
29
|
-
|
|
23
|
+
status_code = error_status_codes[error.status]
|
|
30
24
|
error!({ error: error.description }, status_code, error.headers)
|
|
31
25
|
end
|
|
32
26
|
|
|
33
27
|
private
|
|
34
28
|
|
|
29
|
+
def endpoint
|
|
30
|
+
env['api.endpoint']
|
|
31
|
+
end
|
|
32
|
+
|
|
35
33
|
def doorkeeper_token
|
|
36
|
-
@
|
|
34
|
+
@doorkeeper_token ||= OAuth::Token.authenticate(
|
|
37
35
|
decorated_request,
|
|
38
36
|
*Doorkeeper.configuration.access_token_methods
|
|
39
37
|
)
|
|
@@ -42,6 +40,13 @@ module Doorkeeper
|
|
|
42
40
|
def decorated_request
|
|
43
41
|
AuthorizationDecorator.new(request)
|
|
44
42
|
end
|
|
43
|
+
|
|
44
|
+
def error_status_codes
|
|
45
|
+
{
|
|
46
|
+
unauthorized: 401,
|
|
47
|
+
forbidden: 403
|
|
48
|
+
}
|
|
49
|
+
end
|
|
45
50
|
end
|
|
46
51
|
end
|
|
47
52
|
end
|
|
@@ -5,11 +5,13 @@ module Doorkeeper
|
|
|
5
5
|
module Controller
|
|
6
6
|
private
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
# :doc:
|
|
9
|
+
def authenticate_resource_owner!
|
|
9
10
|
current_resource_owner
|
|
10
11
|
end
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
# :doc:
|
|
14
|
+
def current_resource_owner
|
|
13
15
|
instance_eval(&Doorkeeper.configuration.authenticate_resource_owner)
|
|
14
16
|
end
|
|
15
17
|
|
|
@@ -17,7 +19,8 @@ module Doorkeeper
|
|
|
17
19
|
instance_eval(&Doorkeeper.configuration.resource_owner_from_credentials)
|
|
18
20
|
end
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
# :doc:
|
|
23
|
+
def authenticate_admin!
|
|
21
24
|
instance_eval(&Doorkeeper.configuration.authenticate_admin)
|
|
22
25
|
end
|
|
23
26
|
|
|
@@ -25,12 +28,13 @@ module Doorkeeper
|
|
|
25
28
|
@server ||= Server.new(self)
|
|
26
29
|
end
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
# :doc:
|
|
32
|
+
def doorkeeper_token
|
|
33
|
+
@doorkeeper_token ||= OAuth::Token.authenticate request, *config_methods
|
|
30
34
|
end
|
|
31
35
|
|
|
32
36
|
def config_methods
|
|
33
|
-
@
|
|
37
|
+
@config_methods ||= Doorkeeper.configuration.access_token_methods
|
|
34
38
|
end
|
|
35
39
|
|
|
36
40
|
def get_error_response_from_exception(exception)
|
|
@@ -47,6 +51,11 @@ module Doorkeeper
|
|
|
47
51
|
def skip_authorization?
|
|
48
52
|
!!instance_exec([@server.current_resource_owner, @pre_auth.client], &Doorkeeper.configuration.skip_authorization)
|
|
49
53
|
end
|
|
54
|
+
|
|
55
|
+
def enforce_content_type
|
|
56
|
+
return if request.content_type == 'application/x-www-form-urlencoded'
|
|
57
|
+
render json: {}, status: :unsupported_media_type
|
|
58
|
+
end
|
|
50
59
|
end
|
|
51
60
|
end
|
|
52
61
|
end
|
|
@@ -6,24 +6,16 @@ module Doorkeeper
|
|
|
6
6
|
include Models::Expirable
|
|
7
7
|
include Models::Revocable
|
|
8
8
|
include Models::Accessible
|
|
9
|
+
include Models::Orderable
|
|
9
10
|
include Models::Scopes
|
|
10
|
-
include ActiveModel::MassAssignmentSecurity if defined?(::ProtectedAttributes)
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
if defined?(ActiveRecord::Base) && ActiveRecord::VERSION::MAJOR >= 5
|
|
18
|
-
belongs_to_options[:optional] = true
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
belongs_to :application, belongs_to_options
|
|
22
|
-
|
|
23
|
-
validates :resource_owner_id, :application_id, :token, :expires_in, :redirect_uri, presence: true
|
|
24
|
-
validates :token, uniqueness: true
|
|
12
|
+
# never uses pkce, if pkce migrations were not generated
|
|
13
|
+
def uses_pkce?
|
|
14
|
+
pkce_supported? && code_challenge.present?
|
|
15
|
+
end
|
|
25
16
|
|
|
26
|
-
|
|
17
|
+
def pkce_supported?
|
|
18
|
+
respond_to? :code_challenge
|
|
27
19
|
end
|
|
28
20
|
|
|
29
21
|
module ClassMethods
|
|
@@ -38,16 +30,53 @@ module Doorkeeper
|
|
|
38
30
|
def by_token(token)
|
|
39
31
|
find_by(token: token.to_s)
|
|
40
32
|
end
|
|
41
|
-
end
|
|
42
33
|
|
|
43
|
-
|
|
34
|
+
# Implements PKCE code_challenge encoding without base64 padding as described in the spec.
|
|
35
|
+
# https://tools.ietf.org/html/rfc7636#appendix-A
|
|
36
|
+
# Appendix A. Notes on Implementing Base64url Encoding without Padding
|
|
37
|
+
#
|
|
38
|
+
# This appendix describes how to implement a base64url-encoding
|
|
39
|
+
# function without padding, based upon the standard base64-encoding
|
|
40
|
+
# function that uses padding.
|
|
41
|
+
#
|
|
42
|
+
# To be concrete, example C# code implementing these functions is shown
|
|
43
|
+
# below. Similar code could be used in other languages.
|
|
44
|
+
#
|
|
45
|
+
# static string base64urlencode(byte [] arg)
|
|
46
|
+
# {
|
|
47
|
+
# string s = Convert.ToBase64String(arg); // Regular base64 encoder
|
|
48
|
+
# s = s.Split('=')[0]; // Remove any trailing '='s
|
|
49
|
+
# s = s.Replace('+', '-'); // 62nd char of encoding
|
|
50
|
+
# s = s.Replace('/', '_'); // 63rd char of encoding
|
|
51
|
+
# return s;
|
|
52
|
+
# }
|
|
53
|
+
#
|
|
54
|
+
# An example correspondence between unencoded and encoded values
|
|
55
|
+
# follows. The octet sequence below encodes into the string below,
|
|
56
|
+
# which when decoded, reproduces the octet sequence.
|
|
57
|
+
#
|
|
58
|
+
# 3 236 255 224 193
|
|
59
|
+
#
|
|
60
|
+
# A-z_4ME
|
|
61
|
+
#
|
|
62
|
+
# https://ruby-doc.org/stdlib-2.1.3/libdoc/base64/rdoc/Base64.html#method-i-urlsafe_encode64
|
|
63
|
+
#
|
|
64
|
+
# urlsafe_encode64(bin)
|
|
65
|
+
# Returns the Base64-encoded version of bin. This method complies with
|
|
66
|
+
# “Base 64 Encoding with URL and Filename Safe Alphabet” in RFC 4648.
|
|
67
|
+
# The alphabet uses '-' instead of '+' and '_' instead of '/'.
|
|
44
68
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
69
|
+
# @param code_verifier [#to_s] a one time use value (any object that responds to `#to_s`)
|
|
70
|
+
#
|
|
71
|
+
# @return [#to_s] An encoded code challenge based on the provided verifier suitable for PKCE validation
|
|
72
|
+
def generate_code_challenge(code_verifier)
|
|
73
|
+
padded_result = Base64.urlsafe_encode64(Digest::SHA256.digest(code_verifier))
|
|
74
|
+
padded_result.split('=')[0] # Remove any trailing '='
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def pkce_supported?
|
|
78
|
+
new.pkce_supported?
|
|
79
|
+
end
|
|
51
80
|
end
|
|
52
81
|
end
|
|
53
82
|
end
|