doorkeeper 3.1.0 → 5.6.2
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/CHANGELOG.md +1079 -0
- data/README.md +114 -326
- data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +7 -6
- data/app/controllers/doorkeeper/application_metal_controller.rb +9 -12
- data/app/controllers/doorkeeper/applications_controller.rb +66 -21
- data/app/controllers/doorkeeper/authorizations_controller.rb +100 -18
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +23 -4
- data/app/controllers/doorkeeper/token_info_controller.rb +16 -4
- data/app/controllers/doorkeeper/tokens_controller.rb +138 -22
- data/app/helpers/doorkeeper/dashboard_helper.rb +15 -9
- data/app/views/doorkeeper/applications/_delete_form.html.erb +4 -3
- data/app/views/doorkeeper/applications/_form.html.erb +33 -21
- 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 +40 -16
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
- data/app/views/doorkeeper/authorizations/new.html.erb +17 -11
- data/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +1 -2
- data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +16 -14
- data/config/locales/en.yml +37 -9
- data/lib/doorkeeper/config/abstract_builder.rb +28 -0
- data/lib/doorkeeper/config/option.rb +82 -0
- data/lib/doorkeeper/config/validations.rb +53 -0
- data/lib/doorkeeper/config.rb +602 -142
- data/lib/doorkeeper/engine.rb +22 -7
- data/lib/doorkeeper/errors.rb +37 -10
- 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/authorization_decorator.rb +6 -4
- data/lib/doorkeeper/grape/helpers.rb +24 -12
- data/lib/doorkeeper/helpers/controller.rb +49 -27
- data/lib/doorkeeper/models/access_grant_mixin.rb +99 -16
- data/lib/doorkeeper/models/access_token_mixin.rb +386 -77
- data/lib/doorkeeper/models/application_mixin.rb +73 -30
- data/lib/doorkeeper/models/concerns/accessible.rb +6 -0
- data/lib/doorkeeper/models/concerns/expirable.rb +20 -6
- data/lib/doorkeeper/models/concerns/expiration_time_sql_math.rb +88 -0
- data/lib/doorkeeper/models/concerns/orderable.rb +15 -0
- data/lib/doorkeeper/models/concerns/ownership.rb +4 -2
- data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
- data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
- data/lib/doorkeeper/models/concerns/revocable.rb +13 -2
- data/lib/doorkeeper/models/concerns/scopes.rb +12 -2
- data/lib/doorkeeper/models/concerns/secret_storable.rb +106 -0
- data/lib/doorkeeper/oauth/authorization/code.rb +48 -12
- data/lib/doorkeeper/oauth/authorization/context.rb +17 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +72 -28
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +22 -18
- data/lib/doorkeeper/oauth/authorization_code_request.rb +64 -14
- data/lib/doorkeeper/oauth/base_request.rb +66 -0
- data/lib/doorkeeper/oauth/base_response.rb +31 -0
- data/lib/doorkeeper/oauth/client/credentials.rb +23 -10
- data/lib/doorkeeper/oauth/client.rb +10 -12
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +48 -4
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +17 -9
- data/lib/doorkeeper/oauth/client_credentials/validator.rb +55 -0
- data/lib/doorkeeper/oauth/client_credentials_request.rb +14 -15
- data/lib/doorkeeper/oauth/code_request.rb +8 -12
- data/lib/doorkeeper/oauth/code_response.rb +31 -19
- data/lib/doorkeeper/oauth/error.rb +5 -3
- data/lib/doorkeeper/oauth/error_response.rb +41 -20
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +11 -3
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +24 -19
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +20 -3
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +55 -4
- 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 +31 -5
- data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +46 -18
- data/lib/doorkeeper/oauth/pre_authorization.rb +135 -26
- data/lib/doorkeeper/oauth/refresh_token_request.rb +67 -30
- data/lib/doorkeeper/oauth/scopes.rb +26 -12
- data/lib/doorkeeper/oauth/token.rb +28 -25
- data/lib/doorkeeper/oauth/token_introspection.rb +202 -0
- data/lib/doorkeeper/oauth/token_request.rb +8 -21
- data/lib/doorkeeper/oauth/token_response.rb +14 -10
- data/lib/doorkeeper/oauth.rb +13 -0
- data/lib/doorkeeper/orm/active_record/access_grant.rb +6 -4
- data/lib/doorkeeper/orm/active_record/access_token.rb +5 -17
- data/lib/doorkeeper/orm/active_record/application.rb +6 -20
- data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +69 -0
- data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +81 -0
- data/lib/doorkeeper/orm/active_record/mixins/application.rb +214 -0
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +33 -0
- data/lib/doorkeeper/orm/active_record.rb +36 -26
- data/lib/doorkeeper/rails/helpers.rb +14 -15
- data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
- data/lib/doorkeeper/rails/routes/mapper.rb +4 -2
- data/lib/doorkeeper/rails/routes/mapping.rb +10 -8
- data/lib/doorkeeper/rails/routes/registry.rb +45 -0
- data/lib/doorkeeper/rails/routes.rb +45 -28
- 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 +12 -4
- data/lib/doorkeeper/request/client_credentials.rb +3 -3
- data/lib/doorkeeper/request/code.rb +1 -1
- data/lib/doorkeeper/request/password.rb +5 -4
- data/lib/doorkeeper/request/refresh_token.rb +6 -5
- data/lib/doorkeeper/request/strategy.rb +4 -2
- data/lib/doorkeeper/request/token.rb +1 -1
- data/lib/doorkeeper/request.rb +62 -29
- data/lib/doorkeeper/secret_storing/base.rb +64 -0
- data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
- data/lib/doorkeeper/secret_storing/plain.rb +33 -0
- data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
- data/lib/doorkeeper/server.rb +9 -19
- data/lib/doorkeeper/stale_records_cleaner.rb +24 -0
- data/lib/doorkeeper/validations.rb +5 -2
- data/lib/doorkeeper/version.rb +12 -1
- data/lib/doorkeeper.rb +112 -56
- data/lib/generators/doorkeeper/application_owner_generator.rb +28 -13
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +33 -0
- data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
- data/lib/generators/doorkeeper/install_generator.rb +19 -9
- data/lib/generators/doorkeeper/migration_generator.rb +27 -10
- data/lib/generators/doorkeeper/pkce_generator.rb +33 -0
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +41 -0
- data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
- data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +9 -0
- data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +13 -0
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +8 -0
- data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +417 -32
- data/lib/generators/doorkeeper/templates/migration.rb.erb +88 -0
- data/lib/generators/doorkeeper/views_generator.rb +8 -4
- data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
- metadata +163 -280
- data/.gitignore +0 -14
- data/.hound.yml +0 -13
- data/.rspec +0 -1
- data/.travis.yml +0 -22
- data/CONTRIBUTING.md +0 -45
- data/Gemfile +0 -10
- data/NEWS.md +0 -525
- data/RELEASING.md +0 -17
- data/Rakefile +0 -20
- data/app/validators/redirect_uri_validator.rb +0 -34
- data/doorkeeper.gemspec +0 -27
- data/lib/doorkeeper/oauth/client/methods.rb +0 -18
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +0 -45
- data/lib/doorkeeper/oauth/request_concern.rb +0 -48
- data/lib/generators/doorkeeper/application_scopes_generator.rb +0 -34
- data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb +0 -7
- data/lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb +0 -5
- data/lib/generators/doorkeeper/templates/migration.rb +0 -50
- data/spec/controllers/applications_controller_spec.rb +0 -58
- data/spec/controllers/authorizations_controller_spec.rb +0 -203
- data/spec/controllers/protected_resources_controller_spec.rb +0 -271
- data/spec/controllers/token_info_controller_spec.rb +0 -52
- data/spec/controllers/tokens_controller_spec.rb +0 -88
- data/spec/dummy/Rakefile +0 -7
- data/spec/dummy/app/controllers/application_controller.rb +0 -3
- data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -7
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -12
- data/spec/dummy/app/controllers/home_controller.rb +0 -17
- data/spec/dummy/app/controllers/metal_controller.rb +0 -11
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -11
- data/spec/dummy/app/helpers/application_helper.rb +0 -5
- data/spec/dummy/app/models/user.rb +0 -9
- 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 -57
- data/spec/dummy/config/boot.rb +0 -9
- data/spec/dummy/config/database.yml +0 -15
- data/spec/dummy/config/environment.rb +0 -5
- data/spec/dummy/config/environments/development.rb +0 -29
- data/spec/dummy/config/environments/production.rb +0 -62
- data/spec/dummy/config/environments/test.rb +0 -55
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy/config/initializers/doorkeeper.rb +0 -96
- data/spec/dummy/config/initializers/secret_token.rb +0 -9
- data/spec/dummy/config/initializers/session_store.rb +0 -8
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
- data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
- data/spec/dummy/config/routes.rb +0 -52
- data/spec/dummy/config.ru +0 -4
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -9
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -5
- data/spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb +0 -41
- data/spec/dummy/db/migrate/20130902175349_add_owner_to_application.rb +0 -7
- data/spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb +0 -5
- data/spec/dummy/db/schema.rb +0 -66
- 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 -6
- data/spec/factories.rb +0 -26
- data/spec/generators/application_owner_generator_spec.rb +0 -22
- data/spec/generators/install_generator_spec.rb +0 -31
- data/spec/generators/migration_generator_spec.rb +0 -20
- data/spec/generators/templates/routes.rb +0 -3
- data/spec/generators/views_generator_spec.rb +0 -27
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -24
- data/spec/lib/config_spec.rb +0 -317
- data/spec/lib/doorkeeper_spec.rb +0 -28
- data/spec/lib/models/expirable_spec.rb +0 -51
- data/spec/lib/models/revocable_spec.rb +0 -36
- data/spec/lib/models/scopes_spec.rb +0 -43
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -42
- data/spec/lib/oauth/authorization_code_request_spec.rb +0 -80
- data/spec/lib/oauth/client/credentials_spec.rb +0 -47
- data/spec/lib/oauth/client/methods_spec.rb +0 -54
- data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -44
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -86
- data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -54
- data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
- data/spec/lib/oauth/client_credentials_request_spec.rb +0 -104
- data/spec/lib/oauth/client_spec.rb +0 -39
- data/spec/lib/oauth/code_request_spec.rb +0 -45
- data/spec/lib/oauth/error_response_spec.rb +0 -61
- data/spec/lib/oauth/error_spec.rb +0 -23
- data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -23
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -64
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -20
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -104
- data/spec/lib/oauth/invalid_token_response_spec.rb +0 -28
- data/spec/lib/oauth/password_access_token_request_spec.rb +0 -90
- data/spec/lib/oauth/pre_authorization_spec.rb +0 -155
- data/spec/lib/oauth/refresh_token_request_spec.rb +0 -123
- data/spec/lib/oauth/scopes_spec.rb +0 -123
- data/spec/lib/oauth/token_request_spec.rb +0 -98
- data/spec/lib/oauth/token_response_spec.rb +0 -85
- data/spec/lib/oauth/token_spec.rb +0 -109
- data/spec/lib/request/strategy_spec.rb +0 -53
- data/spec/lib/server_spec.rb +0 -52
- data/spec/models/doorkeeper/access_grant_spec.rb +0 -36
- data/spec/models/doorkeeper/access_token_spec.rb +0 -350
- data/spec/models/doorkeeper/application_spec.rb +0 -187
- data/spec/requests/applications/applications_request_spec.rb +0 -94
- data/spec/requests/applications/authorized_applications_spec.rb +0 -30
- data/spec/requests/endpoints/authorization_spec.rb +0 -72
- data/spec/requests/endpoints/token_spec.rb +0 -64
- data/spec/requests/flows/authorization_code_errors_spec.rb +0 -66
- data/spec/requests/flows/authorization_code_spec.rb +0 -156
- data/spec/requests/flows/client_credentials_spec.rb +0 -58
- data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -32
- data/spec/requests/flows/implicit_grant_spec.rb +0 -61
- data/spec/requests/flows/password_spec.rb +0 -94
- data/spec/requests/flows/refresh_token_spec.rb +0 -104
- data/spec/requests/flows/revoke_token_spec.rb +0 -143
- data/spec/requests/flows/skip_authorization_spec.rb +0 -59
- data/spec/requests/protected_resources/metal_spec.rb +0 -14
- data/spec/requests/protected_resources/private_api_spec.rb +0 -81
- data/spec/routing/custom_controller_routes_spec.rb +0 -71
- data/spec/routing/default_routes_spec.rb +0 -35
- data/spec/routing/scoped_routes_spec.rb +0 -31
- data/spec/spec_helper.rb +0 -2
- data/spec/spec_helper_integration.rb +0 -56
- data/spec/support/dependencies/factory_girl.rb +0 -2
- data/spec/support/helpers/access_token_request_helper.rb +0 -11
- data/spec/support/helpers/authorization_request_helper.rb +0 -41
- data/spec/support/helpers/config_helper.rb +0 -9
- data/spec/support/helpers/model_helper.rb +0 -45
- data/spec/support/helpers/request_spec_helper.rb +0 -76
- data/spec/support/helpers/url_helper.rb +0 -55
- data/spec/support/orm/active_record.rb +0 -3
- data/spec/support/shared/controllers_shared_context.rb +0 -60
- data/spec/support/shared/models_shared_examples.rb +0 -52
- data/spec/validators/redirect_uri_validator_spec.rb +0 -78
@@ -1,54 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
class ApplicationsController < Doorkeeper::ApplicationController
|
3
|
-
layout
|
5
|
+
layout "doorkeeper/admin" unless Doorkeeper.configuration.api_only
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
+
before_action :authenticate_admin!
|
8
|
+
before_action :set_application, only: %i[show edit update destroy]
|
7
9
|
|
8
10
|
def index
|
9
|
-
@applications =
|
11
|
+
@applications = Doorkeeper.config.application_model.ordered_by(:created_at)
|
12
|
+
|
13
|
+
respond_to do |format|
|
14
|
+
format.html
|
15
|
+
format.json { head :no_content }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def show
|
20
|
+
respond_to do |format|
|
21
|
+
format.html
|
22
|
+
format.json { render json: @application, as_owner: true }
|
23
|
+
end
|
10
24
|
end
|
11
25
|
|
12
26
|
def new
|
13
|
-
@application =
|
27
|
+
@application = Doorkeeper.config.application_model.new
|
14
28
|
end
|
15
29
|
|
16
30
|
def create
|
17
|
-
@application =
|
31
|
+
@application = Doorkeeper.config.application_model.new(application_params)
|
32
|
+
|
18
33
|
if @application.save
|
19
|
-
flash[:notice] = I18n.t(:notice, scope: [
|
20
|
-
|
34
|
+
flash[:notice] = I18n.t(:notice, scope: %i[doorkeeper flash applications create])
|
35
|
+
flash[:application_secret] = @application.plaintext_secret
|
36
|
+
|
37
|
+
respond_to do |format|
|
38
|
+
format.html { redirect_to oauth_application_url(@application) }
|
39
|
+
format.json { render json: @application, as_owner: true }
|
40
|
+
end
|
21
41
|
else
|
22
|
-
|
42
|
+
respond_to do |format|
|
43
|
+
format.html { render :new }
|
44
|
+
format.json do
|
45
|
+
errors = @application.errors.full_messages
|
46
|
+
|
47
|
+
render json: { errors: errors }, status: :unprocessable_entity
|
48
|
+
end
|
49
|
+
end
|
23
50
|
end
|
24
51
|
end
|
25
52
|
|
53
|
+
def edit; end
|
54
|
+
|
26
55
|
def update
|
27
|
-
if @application.
|
28
|
-
flash[:notice] = I18n.t(:notice, scope:
|
29
|
-
|
56
|
+
if @application.update(application_params)
|
57
|
+
flash[:notice] = I18n.t(:notice, scope: i18n_scope(:update))
|
58
|
+
|
59
|
+
respond_to do |format|
|
60
|
+
format.html { redirect_to oauth_application_url(@application) }
|
61
|
+
format.json { render json: @application, as_owner: true }
|
62
|
+
end
|
30
63
|
else
|
31
|
-
|
64
|
+
respond_to do |format|
|
65
|
+
format.html { render :edit }
|
66
|
+
format.json do
|
67
|
+
errors = @application.errors.full_messages
|
68
|
+
|
69
|
+
render json: { errors: errors }, status: :unprocessable_entity
|
70
|
+
end
|
71
|
+
end
|
32
72
|
end
|
33
73
|
end
|
34
74
|
|
35
75
|
def destroy
|
36
|
-
flash[:notice] = I18n.t(:notice, scope:
|
37
|
-
|
76
|
+
flash[:notice] = I18n.t(:notice, scope: i18n_scope(:destroy)) if @application.destroy
|
77
|
+
|
78
|
+
respond_to do |format|
|
79
|
+
format.html { redirect_to oauth_applications_url }
|
80
|
+
format.json { head :no_content }
|
81
|
+
end
|
38
82
|
end
|
39
83
|
|
40
84
|
private
|
41
85
|
|
42
86
|
def set_application
|
43
|
-
@application =
|
87
|
+
@application = Doorkeeper.config.application_model.find(params[:id])
|
44
88
|
end
|
45
89
|
|
46
90
|
def application_params
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
91
|
+
params.require(:doorkeeper_application)
|
92
|
+
.permit(:name, :redirect_uri, :scopes, :confidential)
|
93
|
+
end
|
94
|
+
|
95
|
+
def i18n_scope(action)
|
96
|
+
%i[doorkeeper flash applications] << action
|
52
97
|
end
|
53
98
|
end
|
54
99
|
end
|
@@ -1,23 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
class AuthorizationsController < Doorkeeper::ApplicationController
|
3
|
-
|
5
|
+
before_action :authenticate_resource_owner!
|
4
6
|
|
5
7
|
def new
|
6
8
|
if pre_auth.authorizable?
|
7
|
-
|
8
|
-
auth = authorization.authorize
|
9
|
-
redirect_to auth.redirect_uri
|
10
|
-
else
|
11
|
-
render :new
|
12
|
-
end
|
9
|
+
render_success
|
13
10
|
else
|
14
|
-
|
11
|
+
render_error
|
15
12
|
end
|
16
13
|
end
|
17
14
|
|
18
|
-
# TODO: Handle raise invalid authorization
|
19
15
|
def create
|
20
|
-
redirect_or_render
|
16
|
+
redirect_or_render authorize_response
|
21
17
|
end
|
22
18
|
|
23
19
|
def destroy
|
@@ -26,24 +22,82 @@ module Doorkeeper
|
|
26
22
|
|
27
23
|
private
|
28
24
|
|
25
|
+
def render_success
|
26
|
+
if skip_authorization? || matching_token?
|
27
|
+
redirect_or_render(authorize_response)
|
28
|
+
elsif Doorkeeper.configuration.api_only
|
29
|
+
render json: pre_auth
|
30
|
+
else
|
31
|
+
render :new
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def render_error
|
36
|
+
if Doorkeeper.configuration.api_only
|
37
|
+
render json: pre_auth.error_response.body,
|
38
|
+
status: :bad_request
|
39
|
+
else
|
40
|
+
render :error
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Active access token issued for the same client and resource owner with
|
45
|
+
# the same set of the scopes exists?
|
29
46
|
def matching_token?
|
30
|
-
|
31
|
-
|
32
|
-
|
47
|
+
Doorkeeper.config.access_token_model.matching_token_for(
|
48
|
+
pre_auth.client,
|
49
|
+
current_resource_owner,
|
50
|
+
pre_auth.scopes,
|
51
|
+
)
|
33
52
|
end
|
34
53
|
|
35
54
|
def redirect_or_render(auth)
|
36
55
|
if auth.redirectable?
|
37
|
-
|
56
|
+
if Doorkeeper.configuration.api_only
|
57
|
+
if pre_auth.form_post_response?
|
58
|
+
render(
|
59
|
+
json: { status: :post, redirect_uri: pre_auth.redirect_uri, body: auth.body },
|
60
|
+
status: auth.status,
|
61
|
+
)
|
62
|
+
else
|
63
|
+
render(
|
64
|
+
json: { status: :redirect, redirect_uri: auth.redirect_uri },
|
65
|
+
status: auth.status,
|
66
|
+
)
|
67
|
+
end
|
68
|
+
elsif pre_auth.form_post_response?
|
69
|
+
render :form_post
|
70
|
+
else
|
71
|
+
redirect_to auth.redirect_uri, allow_other_host: true
|
72
|
+
end
|
38
73
|
else
|
39
74
|
render json: auth.body, status: auth.status
|
40
75
|
end
|
41
76
|
end
|
42
77
|
|
43
78
|
def pre_auth
|
44
|
-
@pre_auth ||= OAuth::PreAuthorization.new(
|
45
|
-
|
46
|
-
|
79
|
+
@pre_auth ||= OAuth::PreAuthorization.new(
|
80
|
+
Doorkeeper.configuration,
|
81
|
+
pre_auth_params,
|
82
|
+
current_resource_owner,
|
83
|
+
)
|
84
|
+
end
|
85
|
+
|
86
|
+
def pre_auth_params
|
87
|
+
params.slice(*pre_auth_param_fields).permit(*pre_auth_param_fields)
|
88
|
+
end
|
89
|
+
|
90
|
+
def pre_auth_param_fields
|
91
|
+
%i[
|
92
|
+
client_id
|
93
|
+
code_challenge
|
94
|
+
code_challenge_method
|
95
|
+
response_type
|
96
|
+
response_mode
|
97
|
+
redirect_uri
|
98
|
+
scope
|
99
|
+
state
|
100
|
+
]
|
47
101
|
end
|
48
102
|
|
49
103
|
def authorization
|
@@ -51,7 +105,35 @@ module Doorkeeper
|
|
51
105
|
end
|
52
106
|
|
53
107
|
def strategy
|
54
|
-
@strategy ||= server.authorization_request
|
108
|
+
@strategy ||= server.authorization_request(pre_auth.response_type)
|
109
|
+
end
|
110
|
+
|
111
|
+
def authorize_response
|
112
|
+
@authorize_response ||= begin
|
113
|
+
return pre_auth.error_response unless pre_auth.authorizable?
|
114
|
+
|
115
|
+
context = build_context(pre_auth: pre_auth)
|
116
|
+
before_successful_authorization(context)
|
117
|
+
|
118
|
+
auth = strategy.authorize
|
119
|
+
|
120
|
+
context = build_context(auth: auth)
|
121
|
+
after_successful_authorization(context)
|
122
|
+
|
123
|
+
auth
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def build_context(**attributes)
|
128
|
+
Doorkeeper::OAuth::Hooks::Context.new(**attributes)
|
129
|
+
end
|
130
|
+
|
131
|
+
def before_successful_authorization(context = nil)
|
132
|
+
Doorkeeper.config.before_successful_authorization.call(self, context)
|
133
|
+
end
|
134
|
+
|
135
|
+
def after_successful_authorization(context)
|
136
|
+
Doorkeeper.config.after_successful_authorization.call(self, context)
|
55
137
|
end
|
56
138
|
end
|
57
139
|
end
|
@@ -1,14 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
class AuthorizedApplicationsController < Doorkeeper::ApplicationController
|
3
|
-
|
5
|
+
before_action :authenticate_resource_owner!
|
4
6
|
|
5
7
|
def index
|
6
|
-
@applications =
|
8
|
+
@applications = Doorkeeper.config.application_model.authorized_for(current_resource_owner)
|
9
|
+
|
10
|
+
respond_to do |format|
|
11
|
+
format.html
|
12
|
+
format.json { render json: @applications, current_resource_owner: current_resource_owner }
|
13
|
+
end
|
7
14
|
end
|
8
15
|
|
9
16
|
def destroy
|
10
|
-
|
11
|
-
|
17
|
+
Doorkeeper.config.application_model.revoke_tokens_and_grants_for(
|
18
|
+
params[:id],
|
19
|
+
current_resource_owner,
|
20
|
+
)
|
21
|
+
|
22
|
+
respond_to do |format|
|
23
|
+
format.html do
|
24
|
+
redirect_to oauth_authorized_applications_url, notice: I18n.t(
|
25
|
+
:notice, scope: %i[doorkeeper flash authorized_applications destroy],
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
format.json { head :no_content }
|
30
|
+
end
|
12
31
|
end
|
13
32
|
end
|
14
33
|
end
|
@@ -1,13 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
class TokenInfoController < Doorkeeper::ApplicationMetalController
|
3
5
|
def show
|
4
|
-
if doorkeeper_token
|
5
|
-
render json:
|
6
|
+
if doorkeeper_token&.accessible?
|
7
|
+
render json: doorkeeper_token_to_json, status: :ok
|
6
8
|
else
|
7
|
-
error = OAuth::
|
9
|
+
error = OAuth::InvalidTokenResponse.new
|
8
10
|
response.headers.merge!(error.headers)
|
9
|
-
render json: error
|
11
|
+
render json: error_to_json(error), status: error.status
|
10
12
|
end
|
11
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
|
12
24
|
end
|
13
25
|
end
|
@@ -1,45 +1,161 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
class TokensController < Doorkeeper::ApplicationMetalController
|
5
|
+
before_action :validate_presence_of_client, only: [:revoke]
|
6
|
+
|
3
7
|
def create
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
self.status = response.status
|
8
|
+
headers.merge!(authorize_response.headers)
|
9
|
+
render json: authorize_response.body,
|
10
|
+
status: authorize_response.status
|
8
11
|
rescue Errors::DoorkeeperError => e
|
9
|
-
handle_token_exception
|
12
|
+
handle_token_exception(e)
|
10
13
|
end
|
11
14
|
|
12
|
-
# OAuth 2.0 Token Revocation -
|
15
|
+
# OAuth 2.0 Token Revocation - https://datatracker.ietf.org/doc/html/rfc7009
|
13
16
|
def revoke
|
14
|
-
# The authorization server
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
31
|
+
end
|
32
|
+
|
33
|
+
# OAuth 2.0 Token Introspection - https://datatracker.ietf.org/doc/html/rfc7662
|
34
|
+
def introspect
|
35
|
+
introspection = OAuth::TokenIntrospection.new(server, token)
|
36
|
+
|
37
|
+
if introspection.authorized?
|
38
|
+
render json: introspection.to_json, status: 200
|
39
|
+
else
|
40
|
+
error = introspection.error_response
|
41
|
+
headers.merge!(error.headers)
|
42
|
+
render json: error.body, status: error.status
|
19
43
|
end
|
20
|
-
# The authorization server responds with HTTP status code 200 if the
|
21
|
-
# token has been revoked successfully or if the client submitted an invalid token
|
22
|
-
render json: {}, status: 200
|
23
44
|
end
|
24
45
|
|
25
46
|
private
|
26
47
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
+
|
77
|
+
# OAuth 2.0 Section 2.1 defines two client types, "public" & "confidential".
|
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.
|
87
|
+
#
|
88
|
+
# Once a confidential client is authenticated, it must be authorized to
|
89
|
+
# revoke the provided access or refresh token. This ensures one client
|
90
|
+
# cannot revoke another's tokens.
|
91
|
+
#
|
92
|
+
# Doorkeeper determines the client type implicitly via the presence of the
|
93
|
+
# OAuth client associated with a given access or refresh token. Since public
|
94
|
+
# clients authenticate the resource owner via "password" or "implicit" grant
|
95
|
+
# types, they set the application_id as null (since the claim cannot be
|
96
|
+
# verified).
|
97
|
+
#
|
98
|
+
# https://datatracker.ietf.org/doc/html/rfc6749#section-2.1
|
99
|
+
# https://datatracker.ietf.org/doc/html/rfc7009
|
100
|
+
def authorized?
|
101
|
+
# Token belongs to specific client, so we need to check if
|
102
|
+
# authenticated client could access it.
|
103
|
+
if token.application_id? && token.application.confidential?
|
104
|
+
# We authorize client by checking token's application
|
105
|
+
server.client && server.client.application == token.application
|
32
106
|
else
|
33
|
-
|
107
|
+
# Token was issued without client, authorization unnecessary
|
108
|
+
true
|
34
109
|
end
|
35
110
|
end
|
36
111
|
|
112
|
+
def revoke_token
|
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?
|
117
|
+
end
|
118
|
+
|
119
|
+
def token
|
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
|
127
|
+
end
|
128
|
+
|
37
129
|
def strategy
|
38
|
-
@strategy ||= server.token_request
|
130
|
+
@strategy ||= server.token_request(params[:grant_type])
|
39
131
|
end
|
40
132
|
|
41
133
|
def authorize_response
|
42
|
-
@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 }
|
43
159
|
end
|
44
160
|
end
|
45
161
|
end
|
@@ -1,15 +1,21 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper
|
4
|
+
module DashboardHelper
|
5
|
+
def doorkeeper_errors_for(object, method)
|
6
|
+
return if object.errors[method].blank?
|
7
|
+
|
8
|
+
output = object.errors[method].map do |msg|
|
9
|
+
content_tag(:span, class: "invalid-feedback") do
|
6
10
|
msg.capitalize
|
7
11
|
end
|
8
|
-
end
|
12
|
+
end
|
13
|
+
|
14
|
+
safe_join(output)
|
9
15
|
end
|
10
|
-
end
|
11
16
|
|
12
|
-
|
13
|
-
|
17
|
+
def doorkeeper_submit_path(application)
|
18
|
+
application.persisted? ? oauth_application_path(application) : oauth_applications_path
|
19
|
+
end
|
14
20
|
end
|
15
21
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
<%- submit_btn_css ||= 'btn btn-link' %>
|
2
|
-
<%= form_tag oauth_application_path(application) do %>
|
3
|
-
|
4
|
-
|
2
|
+
<%= form_tag oauth_application_path(application), method: :delete do %>
|
3
|
+
<%= submit_tag t('doorkeeper.applications.buttons.destroy'),
|
4
|
+
onclick: "return confirm('#{ t('doorkeeper.applications.confirmations.destroy') }')",
|
5
|
+
class: submit_btn_css %>
|
5
6
|
<% end %>
|
@@ -1,47 +1,59 @@
|
|
1
|
-
<%= form_for application, url: doorkeeper_submit_path(application), html: {
|
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 %>
|
5
5
|
|
6
|
-
|
7
|
-
<%= f.label :name, class: 'col-sm-2
|
6
|
+
<div class="form-group row">
|
7
|
+
<%= f.label :name, class: 'col-sm-2 col-form-label font-weight-bold' %>
|
8
8
|
<div class="col-sm-10">
|
9
|
-
<%= f.text_field :name, class:
|
9
|
+
<%= f.text_field :name, class: "form-control #{ 'is-invalid' if application.errors[:name].present? }", required: true %>
|
10
10
|
<%= doorkeeper_errors_for application, :name %>
|
11
11
|
</div>
|
12
|
-
|
12
|
+
</div>
|
13
13
|
|
14
|
-
|
15
|
-
<%= f.label :redirect_uri, class: 'col-sm-2
|
14
|
+
<div class="form-group row">
|
15
|
+
<%= f.label :redirect_uri, class: 'col-sm-2 col-form-label font-weight-bold' %>
|
16
16
|
<div class="col-sm-10">
|
17
|
-
<%= f.text_area :redirect_uri, class:
|
17
|
+
<%= f.text_area :redirect_uri, class: "form-control #{ 'is-invalid' if application.errors[:redirect_uri].present? }" %>
|
18
18
|
<%= doorkeeper_errors_for application, :redirect_uri %>
|
19
|
-
<span class="
|
19
|
+
<span class="form-text text-secondary">
|
20
20
|
<%= t('doorkeeper.applications.help.redirect_uri') %>
|
21
21
|
</span>
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
|
23
|
+
<% if Doorkeeper.configuration.allow_blank_redirect_uri?(application) %>
|
24
|
+
<span class="form-text text-secondary">
|
25
|
+
<%= t('doorkeeper.applications.help.blank_redirect_uri') %>
|
26
|
+
</span>
|
26
27
|
<% end %>
|
27
28
|
</div>
|
28
|
-
|
29
|
+
</div>
|
30
|
+
|
31
|
+
<div class="form-group row">
|
32
|
+
<%= f.label :confidential, class: 'col-sm-2 form-check-label font-weight-bold' %>
|
33
|
+
<div class="col-sm-10">
|
34
|
+
<%= f.check_box :confidential, class: "checkbox #{ 'is-invalid' if application.errors[:confidential].present? }" %>
|
35
|
+
<%= doorkeeper_errors_for application, :confidential %>
|
36
|
+
<span class="form-text text-secondary">
|
37
|
+
<%= t('doorkeeper.applications.help.confidential') %>
|
38
|
+
</span>
|
39
|
+
</div>
|
40
|
+
</div>
|
29
41
|
|
30
|
-
|
31
|
-
<%= f.label :scopes, class: 'col-sm-2
|
42
|
+
<div class="form-group row">
|
43
|
+
<%= f.label :scopes, class: 'col-sm-2 col-form-label font-weight-bold' %>
|
32
44
|
<div class="col-sm-10">
|
33
|
-
<%= f.text_field :scopes, class:
|
45
|
+
<%= f.text_field :scopes, class: "form-control #{ 'has-error' if application.errors[:scopes].present? }" %>
|
34
46
|
<%= doorkeeper_errors_for application, :scopes %>
|
35
|
-
<span class="
|
47
|
+
<span class="form-text text-secondary">
|
36
48
|
<%= t('doorkeeper.applications.help.scopes') %>
|
37
49
|
</span>
|
38
50
|
</div>
|
39
|
-
|
51
|
+
</div>
|
40
52
|
|
41
53
|
<div class="form-group">
|
42
54
|
<div class="col-sm-offset-2 col-sm-10">
|
43
|
-
<%= f.submit t('doorkeeper.applications.buttons.submit'), class:
|
44
|
-
<%= link_to t('doorkeeper.applications.buttons.cancel'), oauth_applications_path, :
|
55
|
+
<%= f.submit t('doorkeeper.applications.buttons.submit'), class: 'btn btn-primary' %>
|
56
|
+
<%= link_to t('doorkeeper.applications.buttons.cancel'), oauth_applications_path, class: 'btn btn-secondary' %>
|
45
57
|
</div>
|
46
58
|
</div>
|
47
59
|
<% end %>
|