From e97e883ad50774f249c8c694598c25a17227299b Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 7 Sep 2023 16:31:46 +0800 Subject: [PATCH] Add reverseproxy auth for API back with default disabled (#26703) This feature was removed by #22219 to avoid possible CSRF attack. This PR takes reverseproxy auth for API back but with default disabled. To prevent possbile CSRF attack, the responsibility will be the reverseproxy but not Gitea itself. For those want to enable this `ENABLE_REVERSE_PROXY_AUTHENTICATION_API`, they should know what they are doing. --------- Co-authored-by: Giteabot --- custom/conf/app.example.ini | 2 ++ .../content/administration/config-cheat-sheet.en-us.md | 3 ++- modules/setting/service.go | 2 ++ routers/api/v1/api.go | 10 ++++++++-- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index a2fab2fd50..fbaea9dc27 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -759,6 +759,8 @@ LEVEL = Info ;; ;; More detail: https://github.com/gogits/gogs/issues/165 ;ENABLE_REVERSE_PROXY_AUTHENTICATION = false +; Enable this to allow reverse proxy authentication for API requests, the reverse proxy is responsible for ensuring that no CSRF is possible. +;ENABLE_REVERSE_PROXY_AUTHENTICATION_API = false ;ENABLE_REVERSE_PROXY_AUTO_REGISTRATION = false ;ENABLE_REVERSE_PROXY_EMAIL = false ;ENABLE_REVERSE_PROXY_FULL_NAME = false diff --git a/docs/content/administration/config-cheat-sheet.en-us.md b/docs/content/administration/config-cheat-sheet.en-us.md index 7e8befb8b7..f11825aaf2 100644 --- a/docs/content/administration/config-cheat-sheet.en-us.md +++ b/docs/content/administration/config-cheat-sheet.en-us.md @@ -621,7 +621,8 @@ And the following unique queues: BASIC and the user's password. Please note if you disable this you will not be able to access the tokens API endpoints using a password. Further, this only disables BASIC authentication using the password - not tokens or OAuth Basic. -- `ENABLE_REVERSE_PROXY_AUTHENTICATION`: **false**: Enable this to allow reverse proxy authentication. +- `ENABLE_REVERSE_PROXY_AUTHENTICATION`: **false**: Enable this to allow reverse proxy authentication for web requests +- `ENABLE_REVERSE_PROXY_AUTHENTICATION_API`: **false**: Enable this to allow reverse proxy authentication for API requests, the reverse proxy is responsible for ensuring that no CSRF is possible. - `ENABLE_REVERSE_PROXY_AUTO_REGISTRATION`: **false**: Enable this to allow auto-registration for reverse authentication. - `ENABLE_REVERSE_PROXY_EMAIL`: **false**: Enable this to allow to auto-registration with a diff --git a/modules/setting/service.go b/modules/setting/service.go index 74a7e90f7c..3ea1501236 100644 --- a/modules/setting/service.go +++ b/modules/setting/service.go @@ -46,6 +46,7 @@ var Service = struct { EnableNotifyMail bool EnableBasicAuth bool EnableReverseProxyAuth bool + EnableReverseProxyAuthAPI bool EnableReverseProxyAutoRegister bool EnableReverseProxyEmail bool EnableReverseProxyFullName bool @@ -157,6 +158,7 @@ func loadServiceFrom(rootCfg ConfigProvider) { Service.RequireSignInView = sec.Key("REQUIRE_SIGNIN_VIEW").MustBool() Service.EnableBasicAuth = sec.Key("ENABLE_BASIC_AUTHENTICATION").MustBool(true) Service.EnableReverseProxyAuth = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool() + Service.EnableReverseProxyAuthAPI = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION_API").MustBool() Service.EnableReverseProxyAutoRegister = sec.Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool() Service.EnableReverseProxyEmail = sec.Key("ENABLE_REVERSE_PROXY_EMAIL").MustBool() Service.EnableReverseProxyFullName = sec.Key("ENABLE_REVERSE_PROXY_FULL_NAME").MustBool() diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 74e68e9ee2..757b406799 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -333,8 +333,11 @@ func reqExploreSignIn() func(ctx *context.APIContext) { } } -func reqBasicAuth() func(ctx *context.APIContext) { +func reqBasicOrRevProxyAuth() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { + if ctx.IsSigned && setting.Service.EnableReverseProxyAuthAPI && ctx.Data["AuthedMethod"].(string) == auth.ReverseProxyMethodName { + return + } if !ctx.IsBasicAuth { ctx.Error(http.StatusUnauthorized, "reqBasicAuth", "auth required") return @@ -698,6 +701,9 @@ func buildAuthGroup() *auth.Group { &auth.HTTPSign{}, &auth.Basic{}, // FIXME: this should be removed once we don't allow basic auth in API ) + if setting.Service.EnableReverseProxyAuthAPI { + group.Add(&auth.ReverseProxy{}) + } specialAdd(group) return group @@ -800,7 +806,7 @@ func Routes() *web.Route { m.Combo("").Get(user.ListAccessTokens). Post(bind(api.CreateAccessTokenOption{}), reqToken(), user.CreateAccessToken) m.Combo("/{id}").Delete(reqToken(), user.DeleteAccessToken) - }, reqBasicAuth()) + }, reqBasicOrRevProxyAuth()) m.Get("/activities/feeds", user.ListUserActivityFeeds) }, context_service.UserAssignmentAPI())