doorkeeper 5.1.2 → 5.6.6
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/{NEWS.md → CHANGELOG.md} +314 -27
- data/README.md +39 -22
- data/app/controllers/doorkeeper/application_controller.rb +3 -2
- data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
- data/app/controllers/doorkeeper/applications_controller.rb +5 -4
- data/app/controllers/doorkeeper/authorizations_controller.rb +76 -25
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +5 -5
- data/app/controllers/doorkeeper/token_info_controller.rb +12 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +99 -28
- data/app/helpers/doorkeeper/dashboard_helper.rb +1 -1
- data/app/views/doorkeeper/applications/_form.html.erb +1 -7
- data/app/views/doorkeeper/applications/show.html.erb +35 -14
- data/app/views/doorkeeper/authorizations/error.html.erb +3 -1
- data/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
- data/app/views/doorkeeper/authorizations/new.html.erb +16 -14
- data/config/locales/en.yml +16 -3
- data/lib/doorkeeper/config/abstract_builder.rb +28 -0
- data/lib/doorkeeper/config/option.rb +20 -2
- data/lib/doorkeeper/config/validations.rb +53 -0
- data/lib/doorkeeper/config.rb +300 -136
- data/lib/doorkeeper/engine.rb +10 -3
- data/lib/doorkeeper/errors.rb +13 -18
- data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
- data/lib/doorkeeper/grant_flow/flow.rb +44 -0
- data/lib/doorkeeper/grant_flow/registry.rb +50 -0
- data/lib/doorkeeper/grant_flow.rb +45 -0
- data/lib/doorkeeper/grape/helpers.rb +7 -3
- data/lib/doorkeeper/helpers/controller.rb +36 -11
- data/lib/doorkeeper/models/access_grant_mixin.rb +23 -19
- data/lib/doorkeeper/models/access_token_mixin.rb +195 -52
- data/lib/doorkeeper/models/application_mixin.rb +8 -7
- data/lib/doorkeeper/models/concerns/expirable.rb +1 -1
- data/lib/doorkeeper/models/concerns/expiration_time_sql_math.rb +88 -0
- data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
- data/lib/doorkeeper/models/concerns/polymorphic_resource_owner.rb +30 -0
- data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
- data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
- data/lib/doorkeeper/models/concerns/revocable.rb +1 -28
- data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
- data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
- data/lib/doorkeeper/oauth/authorization/code.rb +31 -14
- data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
- data/lib/doorkeeper/oauth/authorization/token.rb +30 -19
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
- data/lib/doorkeeper/oauth/authorization_code_request.rb +51 -22
- data/lib/doorkeeper/oauth/base_request.rb +21 -22
- data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
- data/lib/doorkeeper/oauth/client.rb +8 -9
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +42 -5
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +10 -8
- data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +14 -5
- data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
- data/lib/doorkeeper/oauth/code_request.rb +6 -12
- data/lib/doorkeeper/oauth/code_response.rb +24 -14
- data/lib/doorkeeper/oauth/error.rb +1 -1
- data/lib/doorkeeper/oauth/error_response.rb +11 -13
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +2 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +8 -12
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +10 -7
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +19 -23
- data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
- data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
- data/lib/doorkeeper/oauth/invalid_token_response.rb +7 -4
- data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +34 -11
- data/lib/doorkeeper/oauth/pre_authorization.rb +114 -44
- data/lib/doorkeeper/oauth/refresh_token_request.rb +54 -34
- data/lib/doorkeeper/oauth/token.rb +6 -7
- data/lib/doorkeeper/oauth/token_introspection.rb +28 -22
- data/lib/doorkeeper/oauth/token_request.rb +6 -20
- data/lib/doorkeeper/oauth/token_response.rb +2 -3
- data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
- data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
- data/lib/doorkeeper/orm/active_record/application.rb +5 -149
- data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +63 -0
- data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +77 -0
- data/lib/doorkeeper/orm/active_record/mixins/application.rb +210 -0
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +5 -2
- data/lib/doorkeeper/orm/active_record.rb +29 -22
- data/lib/doorkeeper/rails/helpers.rb +4 -4
- data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
- data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
- data/lib/doorkeeper/rails/routes/registry.rb +45 -0
- data/lib/doorkeeper/rails/routes.rb +28 -27
- data/lib/doorkeeper/rake/db.rake +6 -6
- data/lib/doorkeeper/request/authorization_code.rb +5 -3
- data/lib/doorkeeper/request/client_credentials.rb +2 -2
- data/lib/doorkeeper/request/password.rb +3 -2
- data/lib/doorkeeper/request/refresh_token.rb +5 -4
- data/lib/doorkeeper/request/strategy.rb +2 -2
- data/lib/doorkeeper/request.rb +49 -17
- data/lib/doorkeeper/server.rb +7 -11
- data/lib/doorkeeper/stale_records_cleaner.rb +6 -2
- data/lib/doorkeeper/version.rb +2 -6
- data/lib/doorkeeper.rb +183 -80
- data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +2 -2
- data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
- data/lib/generators/doorkeeper/migration_generator.rb +1 -1
- data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +7 -7
- data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +3 -1
- data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
- data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +230 -50
- data/lib/generators/doorkeeper/templates/migration.rb.erb +31 -9
- metadata +61 -327
- data/.coveralls.yml +0 -1
- data/.github/ISSUE_TEMPLATE.md +0 -25
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
- data/.gitignore +0 -20
- data/.gitlab-ci.yml +0 -16
- data/.hound.yml +0 -3
- data/.rspec +0 -1
- data/.rubocop.yml +0 -50
- data/.travis.yml +0 -35
- data/Appraisals +0 -40
- data/CODE_OF_CONDUCT.md +0 -46
- data/CONTRIBUTING.md +0 -47
- data/Dangerfile +0 -67
- data/Gemfile +0 -24
- data/RELEASING.md +0 -10
- data/Rakefile +0 -28
- data/SECURITY.md +0 -15
- data/UPGRADE.md +0 -2
- data/app/validators/redirect_uri_validator.rb +0 -50
- data/bin/console +0 -16
- data/doorkeeper.gemspec +0 -34
- data/gemfiles/rails_5_0.gemfile +0 -17
- data/gemfiles/rails_5_1.gemfile +0 -17
- data/gemfiles/rails_5_2.gemfile +0 -17
- data/gemfiles/rails_6_0.gemfile +0 -17
- data/gemfiles/rails_master.gemfile +0 -17
- data/spec/controllers/application_metal_controller_spec.rb +0 -64
- data/spec/controllers/applications_controller_spec.rb +0 -180
- data/spec/controllers/authorizations_controller_spec.rb +0 -527
- data/spec/controllers/protected_resources_controller_spec.rb +0 -353
- data/spec/controllers/token_info_controller_spec.rb +0 -50
- data/spec/controllers/tokens_controller_spec.rb +0 -330
- data/spec/dummy/Rakefile +0 -9
- data/spec/dummy/app/assets/config/manifest.js +0 -2
- data/spec/dummy/app/controllers/application_controller.rb +0 -5
- data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
- data/spec/dummy/app/controllers/home_controller.rb +0 -18
- data/spec/dummy/app/controllers/metal_controller.rb +0 -13
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
- data/spec/dummy/app/helpers/application_helper.rb +0 -7
- data/spec/dummy/app/models/user.rb +0 -7
- data/spec/dummy/app/views/home/index.html.erb +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/dummy/config/application.rb +0 -47
- data/spec/dummy/config/boot.rb +0 -7
- data/spec/dummy/config/database.yml +0 -15
- data/spec/dummy/config/environment.rb +0 -5
- data/spec/dummy/config/environments/development.rb +0 -31
- data/spec/dummy/config/environments/production.rb +0 -64
- data/spec/dummy/config/environments/test.rb +0 -45
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
- data/spec/dummy/config/initializers/doorkeeper.rb +0 -121
- data/spec/dummy/config/initializers/secret_token.rb +0 -10
- data/spec/dummy/config/initializers/session_store.rb +0 -10
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
- data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
- data/spec/dummy/config/routes.rb +0 -13
- data/spec/dummy/config.ru +0 -6
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
- data/spec/dummy/db/schema.rb +0 -68
- data/spec/dummy/public/404.html +0 -26
- data/spec/dummy/public/422.html +0 -26
- data/spec/dummy/public/500.html +0 -26
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +0 -9
- data/spec/factories.rb +0 -30
- data/spec/generators/application_owner_generator_spec.rb +0 -28
- data/spec/generators/confidential_applications_generator_spec.rb +0 -29
- data/spec/generators/install_generator_spec.rb +0 -36
- data/spec/generators/migration_generator_spec.rb +0 -28
- data/spec/generators/pkce_generator_spec.rb +0 -28
- data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
- data/spec/generators/templates/routes.rb +0 -4
- data/spec/generators/views_generator_spec.rb +0 -29
- data/spec/grape/grape_integration_spec.rb +0 -137
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
- data/spec/lib/config_spec.rb +0 -697
- data/spec/lib/doorkeeper_spec.rb +0 -27
- data/spec/lib/models/expirable_spec.rb +0 -61
- data/spec/lib/models/reusable_spec.rb +0 -40
- data/spec/lib/models/revocable_spec.rb +0 -59
- data/spec/lib/models/scopes_spec.rb +0 -53
- data/spec/lib/models/secret_storable_spec.rb +0 -135
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
- data/spec/lib/oauth/authorization_code_request_spec.rb +0 -156
- data/spec/lib/oauth/base_request_spec.rb +0 -205
- data/spec/lib/oauth/base_response_spec.rb +0 -47
- data/spec/lib/oauth/client/credentials_spec.rb +0 -90
- data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -94
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
- data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
- data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -29
- data/spec/lib/oauth/client_credentials_request_spec.rb +0 -109
- data/spec/lib/oauth/client_spec.rb +0 -38
- data/spec/lib/oauth/code_request_spec.rb +0 -47
- data/spec/lib/oauth/code_response_spec.rb +0 -36
- data/spec/lib/oauth/error_response_spec.rb +0 -66
- data/spec/lib/oauth/error_spec.rb +0 -23
- data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -22
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -98
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -247
- data/spec/lib/oauth/invalid_token_response_spec.rb +0 -55
- data/spec/lib/oauth/password_access_token_request_spec.rb +0 -192
- data/spec/lib/oauth/pre_authorization_spec.rb +0 -215
- data/spec/lib/oauth/refresh_token_request_spec.rb +0 -177
- data/spec/lib/oauth/scopes_spec.rb +0 -148
- data/spec/lib/oauth/token_request_spec.rb +0 -150
- data/spec/lib/oauth/token_response_spec.rb +0 -86
- data/spec/lib/oauth/token_spec.rb +0 -158
- data/spec/lib/request/strategy_spec.rb +0 -54
- data/spec/lib/secret_storing/base_spec.rb +0 -60
- data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
- data/spec/lib/secret_storing/plain_spec.rb +0 -44
- data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
- data/spec/lib/server_spec.rb +0 -61
- data/spec/lib/stale_records_cleaner_spec.rb +0 -89
- data/spec/models/doorkeeper/access_grant_spec.rb +0 -144
- data/spec/models/doorkeeper/access_token_spec.rb +0 -591
- data/spec/models/doorkeeper/application_spec.rb +0 -472
- data/spec/requests/applications/applications_request_spec.rb +0 -259
- data/spec/requests/applications/authorized_applications_spec.rb +0 -32
- data/spec/requests/endpoints/authorization_spec.rb +0 -73
- data/spec/requests/endpoints/token_spec.rb +0 -75
- data/spec/requests/flows/authorization_code_errors_spec.rb +0 -78
- data/spec/requests/flows/authorization_code_spec.rb +0 -447
- data/spec/requests/flows/client_credentials_spec.rb +0 -128
- data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -34
- data/spec/requests/flows/implicit_grant_spec.rb +0 -90
- data/spec/requests/flows/password_spec.rb +0 -259
- data/spec/requests/flows/refresh_token_spec.rb +0 -233
- data/spec/requests/flows/revoke_token_spec.rb +0 -143
- data/spec/requests/flows/skip_authorization_spec.rb +0 -66
- data/spec/requests/protected_resources/metal_spec.rb +0 -16
- data/spec/requests/protected_resources/private_api_spec.rb +0 -83
- data/spec/routing/custom_controller_routes_spec.rb +0 -133
- data/spec/routing/default_routes_spec.rb +0 -41
- data/spec/routing/scoped_routes_spec.rb +0 -47
- data/spec/spec_helper.rb +0 -57
- data/spec/spec_helper_integration.rb +0 -4
- data/spec/support/dependencies/factory_bot.rb +0 -4
- data/spec/support/doorkeeper_rspec.rb +0 -22
- data/spec/support/helpers/access_token_request_helper.rb +0 -13
- data/spec/support/helpers/authorization_request_helper.rb +0 -43
- data/spec/support/helpers/config_helper.rb +0 -11
- data/spec/support/helpers/model_helper.rb +0 -78
- data/spec/support/helpers/request_spec_helper.rb +0 -98
- data/spec/support/helpers/url_helper.rb +0 -62
- data/spec/support/http_method_shim.rb +0 -29
- data/spec/support/orm/active_record.rb +0 -5
- data/spec/support/shared/controllers_shared_context.rb +0 -123
- data/spec/support/shared/hashing_shared_context.rb +0 -36
- data/spec/support/shared/models_shared_examples.rb +0 -54
- data/spec/validators/redirect_uri_validator_spec.rb +0 -158
- data/spec/version/version_spec.rb +0 -17
@@ -1,11 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Doorkeeper
|
4
|
-
class ApplicationMetalController <
|
4
|
+
class ApplicationMetalController <
|
5
|
+
Doorkeeper.config.resolve_controller(:base_metal)
|
5
6
|
include Helpers::Controller
|
6
7
|
|
7
8
|
before_action :enforce_content_type,
|
8
|
-
if: -> { Doorkeeper.
|
9
|
+
if: -> { Doorkeeper.config.enforce_content_type }
|
9
10
|
|
10
11
|
ActiveSupport.run_load_hooks(:doorkeeper_metal_controller, self)
|
11
12
|
end
|
@@ -8,7 +8,7 @@ module Doorkeeper
|
|
8
8
|
before_action :set_application, only: %i[show edit update destroy]
|
9
9
|
|
10
10
|
def index
|
11
|
-
@applications =
|
11
|
+
@applications = Doorkeeper.config.application_model.ordered_by(:created_at)
|
12
12
|
|
13
13
|
respond_to do |format|
|
14
14
|
format.html
|
@@ -24,14 +24,15 @@ module Doorkeeper
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def new
|
27
|
-
@application =
|
27
|
+
@application = Doorkeeper.config.application_model.new
|
28
28
|
end
|
29
29
|
|
30
30
|
def create
|
31
|
-
@application =
|
31
|
+
@application = Doorkeeper.config.application_model.new(application_params)
|
32
32
|
|
33
33
|
if @application.save
|
34
34
|
flash[:notice] = I18n.t(:notice, scope: %i[doorkeeper flash applications create])
|
35
|
+
flash[:application_secret] = @application.plaintext_secret
|
35
36
|
|
36
37
|
respond_to do |format|
|
37
38
|
format.html { redirect_to oauth_application_url(@application) }
|
@@ -83,7 +84,7 @@ module Doorkeeper
|
|
83
84
|
private
|
84
85
|
|
85
86
|
def set_application
|
86
|
-
@application =
|
87
|
+
@application = Doorkeeper.config.application_model.find(params[:id])
|
87
88
|
end
|
88
89
|
|
89
90
|
def application_params
|
@@ -12,20 +12,27 @@ module Doorkeeper
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
# TODO: Handle raise invalid authorization
|
16
15
|
def create
|
17
|
-
redirect_or_render
|
16
|
+
redirect_or_render(authorize_response)
|
18
17
|
end
|
19
18
|
|
20
19
|
def destroy
|
21
|
-
redirect_or_render
|
20
|
+
redirect_or_render(authorization.deny)
|
21
|
+
rescue Doorkeeper::Errors::InvalidTokenStrategy => e
|
22
|
+
error_response = get_error_response_from_exception(e)
|
23
|
+
|
24
|
+
if Doorkeeper.configuration.api_only
|
25
|
+
render json: error_response.body, status: :bad_request
|
26
|
+
else
|
27
|
+
render :error, locals: { error_response: error_response }
|
28
|
+
end
|
22
29
|
end
|
23
30
|
|
24
31
|
private
|
25
32
|
|
26
33
|
def render_success
|
27
|
-
if skip_authorization? || matching_token?
|
28
|
-
redirect_or_render
|
34
|
+
if skip_authorization? || (matching_token? && pre_auth.client.application.confidential?)
|
35
|
+
redirect_or_render(authorize_response)
|
29
36
|
elsif Doorkeeper.configuration.api_only
|
30
37
|
render json: pre_auth
|
31
38
|
else
|
@@ -38,27 +45,38 @@ module Doorkeeper
|
|
38
45
|
render json: pre_auth.error_response.body,
|
39
46
|
status: :bad_request
|
40
47
|
else
|
41
|
-
render :error
|
48
|
+
render :error, locals: { error_response: pre_auth.error_response }
|
42
49
|
end
|
43
50
|
end
|
44
51
|
|
52
|
+
# Active access token issued for the same client and resource owner with
|
53
|
+
# the same set of the scopes exists?
|
45
54
|
def matching_token?
|
46
|
-
|
55
|
+
Doorkeeper.config.access_token_model.matching_token_for(
|
47
56
|
pre_auth.client,
|
48
|
-
current_resource_owner
|
49
|
-
pre_auth.scopes
|
57
|
+
current_resource_owner,
|
58
|
+
pre_auth.scopes,
|
50
59
|
)
|
51
60
|
end
|
52
61
|
|
53
62
|
def redirect_or_render(auth)
|
54
63
|
if auth.redirectable?
|
55
64
|
if Doorkeeper.configuration.api_only
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
65
|
+
if pre_auth.form_post_response?
|
66
|
+
render(
|
67
|
+
json: { status: :post, redirect_uri: pre_auth.redirect_uri, body: auth.body },
|
68
|
+
status: auth.status,
|
69
|
+
)
|
70
|
+
else
|
71
|
+
render(
|
72
|
+
json: { status: :redirect, redirect_uri: auth.redirect_uri },
|
73
|
+
status: auth.status,
|
74
|
+
)
|
75
|
+
end
|
76
|
+
elsif pre_auth.form_post_response?
|
77
|
+
render :form_post
|
60
78
|
else
|
61
|
-
redirect_to auth.redirect_uri
|
79
|
+
redirect_to auth.redirect_uri, allow_other_host: true
|
62
80
|
end
|
63
81
|
else
|
64
82
|
render json: auth.body, status: auth.status
|
@@ -66,9 +84,32 @@ module Doorkeeper
|
|
66
84
|
end
|
67
85
|
|
68
86
|
def pre_auth
|
69
|
-
@pre_auth ||= OAuth::PreAuthorization.new(
|
70
|
-
|
71
|
-
|
87
|
+
@pre_auth ||= OAuth::PreAuthorization.new(
|
88
|
+
Doorkeeper.configuration,
|
89
|
+
pre_auth_params,
|
90
|
+
current_resource_owner,
|
91
|
+
)
|
92
|
+
end
|
93
|
+
|
94
|
+
def pre_auth_params
|
95
|
+
params.slice(*pre_auth_param_fields).permit(*pre_auth_param_fields)
|
96
|
+
end
|
97
|
+
|
98
|
+
def pre_auth_param_fields
|
99
|
+
custom_access_token_attributes + %i[
|
100
|
+
client_id
|
101
|
+
code_challenge
|
102
|
+
code_challenge_method
|
103
|
+
response_type
|
104
|
+
response_mode
|
105
|
+
redirect_uri
|
106
|
+
scope
|
107
|
+
state
|
108
|
+
]
|
109
|
+
end
|
110
|
+
|
111
|
+
def custom_access_token_attributes
|
112
|
+
Doorkeeper.config.custom_access_token_attributes.map(&:to_sym)
|
72
113
|
end
|
73
114
|
|
74
115
|
def authorization
|
@@ -76,25 +117,35 @@ module Doorkeeper
|
|
76
117
|
end
|
77
118
|
|
78
119
|
def strategy
|
79
|
-
@strategy ||= server.authorization_request
|
120
|
+
@strategy ||= server.authorization_request(pre_auth.response_type)
|
80
121
|
end
|
81
122
|
|
82
123
|
def authorize_response
|
83
124
|
@authorize_response ||= begin
|
84
|
-
|
85
|
-
|
125
|
+
return pre_auth.error_response unless pre_auth.authorizable?
|
126
|
+
|
127
|
+
context = build_context(pre_auth: pre_auth)
|
128
|
+
before_successful_authorization(context)
|
129
|
+
|
86
130
|
auth = strategy.authorize
|
87
|
-
|
131
|
+
|
132
|
+
context = build_context(auth: auth)
|
133
|
+
after_successful_authorization(context)
|
134
|
+
|
88
135
|
auth
|
89
136
|
end
|
90
137
|
end
|
91
138
|
|
92
|
-
def
|
93
|
-
Doorkeeper.
|
139
|
+
def build_context(**attributes)
|
140
|
+
Doorkeeper::OAuth::Hooks::Context.new(**attributes)
|
141
|
+
end
|
142
|
+
|
143
|
+
def before_successful_authorization(context = nil)
|
144
|
+
Doorkeeper.config.before_successful_authorization.call(self, context)
|
94
145
|
end
|
95
146
|
|
96
|
-
def
|
97
|
-
Doorkeeper.
|
147
|
+
def after_successful_authorization(context)
|
148
|
+
Doorkeeper.config.after_successful_authorization.call(self, context)
|
98
149
|
end
|
99
150
|
end
|
100
151
|
end
|
@@ -5,7 +5,7 @@ module Doorkeeper
|
|
5
5
|
before_action :authenticate_resource_owner!
|
6
6
|
|
7
7
|
def index
|
8
|
-
@applications =
|
8
|
+
@applications = Doorkeeper.config.application_model.authorized_for(current_resource_owner)
|
9
9
|
|
10
10
|
respond_to do |format|
|
11
11
|
format.html
|
@@ -14,19 +14,19 @@ module Doorkeeper
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def destroy
|
17
|
-
|
17
|
+
Doorkeeper.config.application_model.revoke_tokens_and_grants_for(
|
18
18
|
params[:id],
|
19
|
-
current_resource_owner
|
19
|
+
current_resource_owner,
|
20
20
|
)
|
21
21
|
|
22
22
|
respond_to do |format|
|
23
23
|
format.html do
|
24
24
|
redirect_to oauth_authorized_applications_url, notice: I18n.t(
|
25
|
-
:notice, scope: %i[doorkeeper flash authorized_applications destroy]
|
25
|
+
:notice, scope: %i[doorkeeper flash authorized_applications destroy],
|
26
26
|
)
|
27
27
|
end
|
28
28
|
|
29
|
-
format.json {
|
29
|
+
format.json { head :no_content }
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
@@ -4,12 +4,22 @@ module Doorkeeper
|
|
4
4
|
class TokenInfoController < Doorkeeper::ApplicationMetalController
|
5
5
|
def show
|
6
6
|
if doorkeeper_token&.accessible?
|
7
|
-
render json:
|
7
|
+
render json: doorkeeper_token_to_json, status: :ok
|
8
8
|
else
|
9
9
|
error = OAuth::InvalidTokenResponse.new
|
10
10
|
response.headers.merge!(error.headers)
|
11
|
-
render json: error
|
11
|
+
render json: error_to_json(error), status: error.status
|
12
12
|
end
|
13
13
|
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def doorkeeper_token_to_json
|
18
|
+
doorkeeper_token
|
19
|
+
end
|
20
|
+
|
21
|
+
def error_to_json(error)
|
22
|
+
error.body
|
23
|
+
end
|
14
24
|
end
|
15
25
|
end
|
@@ -2,30 +2,35 @@
|
|
2
2
|
|
3
3
|
module Doorkeeper
|
4
4
|
class TokensController < Doorkeeper::ApplicationMetalController
|
5
|
+
before_action :validate_presence_of_client, only: [:revoke]
|
6
|
+
|
5
7
|
def create
|
6
8
|
headers.merge!(authorize_response.headers)
|
7
9
|
render json: authorize_response.body,
|
8
10
|
status: authorize_response.status
|
9
|
-
rescue Errors::DoorkeeperError =>
|
10
|
-
handle_token_exception(
|
11
|
+
rescue Errors::DoorkeeperError => e
|
12
|
+
handle_token_exception(e)
|
11
13
|
end
|
12
14
|
|
13
|
-
# OAuth 2.0 Token Revocation -
|
15
|
+
# OAuth 2.0 Token Revocation - https://datatracker.ietf.org/doc/html/rfc7009
|
14
16
|
def revoke
|
15
|
-
# The authorization server
|
16
|
-
#
|
17
|
-
|
18
|
-
|
19
|
-
#
|
20
|
-
# the
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
17
|
+
# The authorization server responds with HTTP status code 200 if the client
|
18
|
+
# submitted an invalid token or the token has been revoked successfully.
|
19
|
+
if token.blank?
|
20
|
+
render json: {}, status: 200
|
21
|
+
# The authorization server validates [...] and whether the token
|
22
|
+
# was issued to the client making the revocation request. If this
|
23
|
+
# validation fails, the request is refused and the client is informed
|
24
|
+
# of the error by the authorization server as described below.
|
25
|
+
elsif authorized?
|
26
|
+
revoke_token
|
27
|
+
render json: {}, status: 200
|
28
|
+
else
|
29
|
+
render json: revocation_error_response, status: :forbidden
|
30
|
+
end
|
27
31
|
end
|
28
32
|
|
33
|
+
# OAuth 2.0 Token Introspection - https://datatracker.ietf.org/doc/html/rfc7662
|
29
34
|
def introspect
|
30
35
|
introspection = OAuth::TokenIntrospection.new(server, token)
|
31
36
|
|
@@ -40,9 +45,45 @@ module Doorkeeper
|
|
40
45
|
|
41
46
|
private
|
42
47
|
|
48
|
+
def validate_presence_of_client
|
49
|
+
return if Doorkeeper.config.skip_client_authentication_for_password_grant
|
50
|
+
|
51
|
+
# @see 2.1. Revocation Request
|
52
|
+
#
|
53
|
+
# The client constructs the request by including the following
|
54
|
+
# parameters using the "application/x-www-form-urlencoded" format in
|
55
|
+
# the HTTP request entity-body:
|
56
|
+
# token REQUIRED.
|
57
|
+
# token_type_hint OPTIONAL.
|
58
|
+
#
|
59
|
+
# The client also includes its authentication credentials as described
|
60
|
+
# in Section 2.3. of [RFC6749].
|
61
|
+
#
|
62
|
+
# The authorization server first validates the client credentials (in
|
63
|
+
# case of a confidential client) and then verifies whether the token
|
64
|
+
# was issued to the client making the revocation request.
|
65
|
+
return if server.client
|
66
|
+
|
67
|
+
# If this validation [client credentials / token ownership] fails, the request is
|
68
|
+
# refused and the client is informed of the error by the authorization server as
|
69
|
+
# described below.
|
70
|
+
#
|
71
|
+
# @see 2.2.1. Error Response
|
72
|
+
#
|
73
|
+
# The error presentation conforms to the definition in Section 5.2 of [RFC6749].
|
74
|
+
render json: revocation_error_response, status: :forbidden
|
75
|
+
end
|
76
|
+
|
43
77
|
# OAuth 2.0 Section 2.1 defines two client types, "public" & "confidential".
|
44
|
-
#
|
45
|
-
#
|
78
|
+
#
|
79
|
+
# RFC7009
|
80
|
+
# Section 5. Security Considerations
|
81
|
+
# A malicious client may attempt to guess valid tokens on this endpoint
|
82
|
+
# by making revocation requests against potential token strings.
|
83
|
+
# According to this specification, a client's request must contain a
|
84
|
+
# valid client_id, in the case of a public client, or valid client
|
85
|
+
# credentials, in the case of a confidential client. The token being
|
86
|
+
# revoked must also belong to the requesting client.
|
46
87
|
#
|
47
88
|
# Once a confidential client is authenticated, it must be authorized to
|
48
89
|
# revoke the provided access or refresh token. This ensures one client
|
@@ -54,29 +95,35 @@ module Doorkeeper
|
|
54
95
|
# types, they set the application_id as null (since the claim cannot be
|
55
96
|
# verified).
|
56
97
|
#
|
57
|
-
# https://
|
58
|
-
# https://
|
98
|
+
# https://datatracker.ietf.org/doc/html/rfc6749#section-2.1
|
99
|
+
# https://datatracker.ietf.org/doc/html/rfc7009
|
59
100
|
def authorized?
|
60
|
-
|
61
|
-
|
62
|
-
# Client is confidential, therefore client authentication & authorization
|
63
|
-
# is required
|
101
|
+
# Token belongs to specific client, so we need to check if
|
102
|
+
# authenticated client could access it.
|
64
103
|
if token.application_id? && token.application.confidential?
|
65
104
|
# We authorize client by checking token's application
|
66
105
|
server.client && server.client.application == token.application
|
67
106
|
else
|
68
|
-
#
|
107
|
+
# Token was issued without client, authorization unnecessary
|
69
108
|
true
|
70
109
|
end
|
71
110
|
end
|
72
111
|
|
73
112
|
def revoke_token
|
74
|
-
|
113
|
+
# The authorization server responds with HTTP status code 200 if the token
|
114
|
+
# has been revoked successfully or if the client submitted an invalid
|
115
|
+
# token
|
116
|
+
token.revoke if token&.accessible?
|
75
117
|
end
|
76
118
|
|
77
119
|
def token
|
78
|
-
@token ||=
|
79
|
-
|
120
|
+
@token ||=
|
121
|
+
if params[:token_type_hint] == "refresh_token"
|
122
|
+
Doorkeeper.config.access_token_model.by_refresh_token(params["token"])
|
123
|
+
else
|
124
|
+
Doorkeeper.config.access_token_model.by_token(params["token"]) ||
|
125
|
+
Doorkeeper.config.access_token_model.by_refresh_token(params["token"])
|
126
|
+
end
|
80
127
|
end
|
81
128
|
|
82
129
|
def strategy
|
@@ -84,7 +131,31 @@ module Doorkeeper
|
|
84
131
|
end
|
85
132
|
|
86
133
|
def authorize_response
|
87
|
-
@authorize_response ||=
|
134
|
+
@authorize_response ||= begin
|
135
|
+
before_successful_authorization
|
136
|
+
auth = strategy.authorize
|
137
|
+
context = build_context(auth: auth)
|
138
|
+
after_successful_authorization(context) unless auth.is_a?(Doorkeeper::OAuth::ErrorResponse)
|
139
|
+
auth
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def build_context(**attributes)
|
144
|
+
Doorkeeper::OAuth::Hooks::Context.new(**attributes)
|
145
|
+
end
|
146
|
+
|
147
|
+
def before_successful_authorization(context = nil)
|
148
|
+
Doorkeeper.config.before_successful_authorization.call(self, context)
|
149
|
+
end
|
150
|
+
|
151
|
+
def after_successful_authorization(context)
|
152
|
+
Doorkeeper.config.after_successful_authorization.call(self, context)
|
153
|
+
end
|
154
|
+
|
155
|
+
def revocation_error_response
|
156
|
+
error_description = I18n.t(:unauthorized, scope: %i[doorkeeper errors messages revoke])
|
157
|
+
|
158
|
+
{ error: :unauthorized_client, error_description: error_description }
|
88
159
|
end
|
89
160
|
end
|
90
161
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<%= form_for application, url: doorkeeper_submit_path(application), html: { role: 'form' } do |f| %>
|
1
|
+
<%= form_for application, url: doorkeeper_submit_path(application), as: :doorkeeper_application, html: { role: 'form' } do |f| %>
|
2
2
|
<% if application.errors.any? %>
|
3
3
|
<div class="alert alert-danger" data-alert><p><%= t('doorkeeper.applications.form.error') %></p></div>
|
4
4
|
<% end %>
|
@@ -20,12 +20,6 @@
|
|
20
20
|
<%= t('doorkeeper.applications.help.redirect_uri') %>
|
21
21
|
</span>
|
22
22
|
|
23
|
-
<% if Doorkeeper.configuration.native_redirect_uri %>
|
24
|
-
<span class="form-text text-secondary">
|
25
|
-
<%= raw t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: content_tag(:code, class: 'bg-light') { Doorkeeper.configuration.native_redirect_uri }) %>
|
26
|
-
</span>
|
27
|
-
<% end %>
|
28
|
-
|
29
23
|
<% if Doorkeeper.configuration.allow_blank_redirect_uri?(application) %>
|
30
24
|
<span class="form-text text-secondary">
|
31
25
|
<%= t('doorkeeper.applications.help.blank_redirect_uri') %>
|
@@ -8,28 +8,49 @@
|
|
8
8
|
<p><code class="bg-light" id="application_id"><%= @application.uid %></code></p>
|
9
9
|
|
10
10
|
<h4><%= t('.secret') %>:</h4>
|
11
|
-
<p
|
11
|
+
<p>
|
12
|
+
<code class="bg-light" id="secret">
|
13
|
+
<% secret = flash[:application_secret].presence || @application.plaintext_secret %>
|
14
|
+
<% if secret.blank? && Doorkeeper.config.application_secret_hashed? %>
|
15
|
+
<span class="bg-light font-italic text-uppercase text-muted"><%= t('.secret_hashed') %></span>
|
16
|
+
<% else %>
|
17
|
+
<%= secret %>
|
18
|
+
<% end %>
|
19
|
+
</code>
|
20
|
+
</p>
|
12
21
|
|
13
22
|
<h4><%= t('.scopes') %>:</h4>
|
14
|
-
<p
|
23
|
+
<p>
|
24
|
+
<code class="bg-light" id="scopes">
|
25
|
+
<% if @application.scopes.present? %>
|
26
|
+
<%= @application.scopes %>
|
27
|
+
<% else %>
|
28
|
+
<span class="bg-light font-italic text-uppercase text-muted"><%= t('.not_defined') %></span>
|
29
|
+
<% end %>
|
30
|
+
</code>
|
31
|
+
</p>
|
15
32
|
|
16
33
|
<h4><%= t('.confidential') %>:</h4>
|
17
34
|
<p><code class="bg-light" id="confidential"><%= @application.confidential? %></code></p>
|
18
35
|
|
19
36
|
<h4><%= t('.callback_urls') %>:</h4>
|
20
37
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
<
|
25
|
-
<
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
38
|
+
<% if @application.redirect_uri.present? %>
|
39
|
+
<table>
|
40
|
+
<% @application.redirect_uri.split.each do |uri| %>
|
41
|
+
<tr>
|
42
|
+
<td>
|
43
|
+
<code class="bg-light"><%= uri %></code>
|
44
|
+
</td>
|
45
|
+
<td>
|
46
|
+
<%= link_to t('doorkeeper.applications.buttons.authorize'), oauth_authorization_path(client_id: @application.uid, redirect_uri: uri, response_type: 'code', scope: @application.scopes), class: 'btn btn-success', target: '_blank' %>
|
47
|
+
</td>
|
48
|
+
</tr>
|
49
|
+
<% end %>
|
50
|
+
</table>
|
51
|
+
<% else %>
|
52
|
+
<span class="bg-light font-italic text-uppercase text-muted"><%= t('.not_defined') %></span>
|
53
|
+
<% end %>
|
33
54
|
</div>
|
34
55
|
|
35
56
|
<div class="col-md-4">
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<header class="page-header">
|
2
|
+
<h1><%= t('.title') %></h1>
|
3
|
+
</header>
|
4
|
+
|
5
|
+
<%= form_tag @pre_auth.redirect_uri, method: :post, name: :redirect_form, authenticity_token: false do %>
|
6
|
+
<% @authorize_response.body.compact.each do |key, value| %>
|
7
|
+
<%= hidden_field_tag key, value %>
|
8
|
+
<% end %>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<script>
|
12
|
+
window.onload = function () {
|
13
|
+
document.forms['redirect_form'].submit();
|
14
|
+
};
|
15
|
+
</script>
|
@@ -21,23 +21,25 @@
|
|
21
21
|
|
22
22
|
<div class="actions">
|
23
23
|
<%= form_tag oauth_authorization_path, method: :post do %>
|
24
|
-
<%= hidden_field_tag :client_id, @pre_auth.client.uid %>
|
25
|
-
<%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri %>
|
26
|
-
<%= hidden_field_tag :state, @pre_auth.state %>
|
27
|
-
<%= hidden_field_tag :response_type, @pre_auth.response_type %>
|
28
|
-
<%= hidden_field_tag :
|
29
|
-
<%= hidden_field_tag :
|
30
|
-
<%= hidden_field_tag :
|
24
|
+
<%= hidden_field_tag :client_id, @pre_auth.client.uid, id: nil %>
|
25
|
+
<%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri, id: nil %>
|
26
|
+
<%= hidden_field_tag :state, @pre_auth.state, id: nil %>
|
27
|
+
<%= hidden_field_tag :response_type, @pre_auth.response_type, id: nil %>
|
28
|
+
<%= hidden_field_tag :response_mode, @pre_auth.response_mode, id: nil %>
|
29
|
+
<%= hidden_field_tag :scope, @pre_auth.scope, id: nil %>
|
30
|
+
<%= hidden_field_tag :code_challenge, @pre_auth.code_challenge, id: nil %>
|
31
|
+
<%= hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method, id: nil %>
|
31
32
|
<%= submit_tag t('doorkeeper.authorizations.buttons.authorize'), class: "btn btn-success btn-lg btn-block" %>
|
32
33
|
<% end %>
|
33
34
|
<%= form_tag oauth_authorization_path, method: :delete do %>
|
34
|
-
<%= hidden_field_tag :client_id, @pre_auth.client.uid %>
|
35
|
-
<%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri %>
|
36
|
-
<%= hidden_field_tag :state, @pre_auth.state %>
|
37
|
-
<%= hidden_field_tag :response_type, @pre_auth.response_type %>
|
38
|
-
<%= hidden_field_tag :
|
39
|
-
<%= hidden_field_tag :
|
40
|
-
<%= hidden_field_tag :
|
35
|
+
<%= hidden_field_tag :client_id, @pre_auth.client.uid, id: nil %>
|
36
|
+
<%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri, id: nil %>
|
37
|
+
<%= hidden_field_tag :state, @pre_auth.state, id: nil %>
|
38
|
+
<%= hidden_field_tag :response_type, @pre_auth.response_type, id: nil %>
|
39
|
+
<%= hidden_field_tag :response_mode, @pre_auth.response_mode, id: nil %>
|
40
|
+
<%= hidden_field_tag :scope, @pre_auth.scope, id: nil %>
|
41
|
+
<%= hidden_field_tag :code_challenge, @pre_auth.code_challenge, id: nil %>
|
42
|
+
<%= hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method, id: nil %>
|
41
43
|
<%= submit_tag t('doorkeeper.authorizations.buttons.deny'), class: "btn btn-danger btn-lg btn-block" %>
|
42
44
|
<% end %>
|
43
45
|
</div>
|