Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions modules/setting/reverseproxy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package setting

var ReverseProxy = struct {
EnableAuth bool
EnableAuthAPI bool
EnableAutoRegister bool
EnableEmail bool
EnableFullName bool

AuthUser string
AuthEmail string
AuthFullName string
Limit int
TrustedProxies []string
}{}

func loadReverseProxyFrom(rootCfg ConfigProvider) {
serviceSec := rootCfg.Section("service")
ReverseProxy.EnableAuth = serviceSec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool()
ReverseProxy.EnableAuthAPI = serviceSec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION_API").MustBool()
ReverseProxy.EnableAutoRegister = serviceSec.Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool()
ReverseProxy.EnableEmail = serviceSec.Key("ENABLE_REVERSE_PROXY_EMAIL").MustBool()
ReverseProxy.EnableFullName = serviceSec.Key("ENABLE_REVERSE_PROXY_FULL_NAME").MustBool()

securitySec := rootCfg.Section("security")
ReverseProxy.AuthUser = securitySec.Key("REVERSE_PROXY_AUTHENTICATION_USER").MustString("X-WEBAUTH-USER")
ReverseProxy.AuthEmail = securitySec.Key("REVERSE_PROXY_AUTHENTICATION_EMAIL").MustString("X-WEBAUTH-EMAIL")
ReverseProxy.AuthFullName = securitySec.Key("REVERSE_PROXY_AUTHENTICATION_FULL_NAME").MustString("X-WEBAUTH-FULLNAME")
ReverseProxy.Limit = securitySec.Key("REVERSE_PROXY_LIMIT").MustInt(1)
ReverseProxy.TrustedProxies = securitySec.Key("REVERSE_PROXY_TRUSTED_PROXIES").Strings(",")
if len(ReverseProxy.TrustedProxies) == 0 {
ReverseProxy.TrustedProxies = []string{"127.0.0.0/8", "::1/128"}
}
}
15 changes: 0 additions & 15 deletions modules/setting/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@ var (
InternalToken string // internal access token
LogInRememberDays int
CookieRememberName string
ReverseProxyAuthUser string
ReverseProxyAuthEmail string
ReverseProxyAuthFullName string
ReverseProxyLimit int
ReverseProxyTrustedProxies []string
MinPasswordLength int
ImportLocalPaths bool
DisableGitHooks = true
Expand Down Expand Up @@ -116,16 +111,6 @@ func loadSecurityFrom(rootCfg ConfigProvider) {

CookieRememberName = sec.Key("COOKIE_REMEMBER_NAME").MustString("gitea_incredible")

ReverseProxyAuthUser = sec.Key("REVERSE_PROXY_AUTHENTICATION_USER").MustString("X-WEBAUTH-USER")
ReverseProxyAuthEmail = sec.Key("REVERSE_PROXY_AUTHENTICATION_EMAIL").MustString("X-WEBAUTH-EMAIL")
ReverseProxyAuthFullName = sec.Key("REVERSE_PROXY_AUTHENTICATION_FULL_NAME").MustString("X-WEBAUTH-FULLNAME")

ReverseProxyLimit = sec.Key("REVERSE_PROXY_LIMIT").MustInt(1)
ReverseProxyTrustedProxies = sec.Key("REVERSE_PROXY_TRUSTED_PROXIES").Strings(",")
if len(ReverseProxyTrustedProxies) == 0 {
ReverseProxyTrustedProxies = []string{"127.0.0.0/8", "::1/128"}
}

MinPasswordLength = sec.Key("MIN_PASSWORD_LENGTH").MustInt(8)
ImportLocalPaths = sec.Key("IMPORT_LOCAL_PATHS").MustBool(false)
DisableGitHooks = sec.Key("DISABLE_GIT_HOOKS").MustBool(true)
Expand Down
10 changes: 0 additions & 10 deletions modules/setting/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ var Service = struct {
EnableNotifyMail bool
EnableBasicAuth bool
EnablePasskeyAuth bool
EnableReverseProxyAuth bool
EnableReverseProxyAuthAPI bool
EnableReverseProxyAutoRegister bool
EnableReverseProxyEmail bool
EnableReverseProxyFullName bool
EnableCaptcha bool
RequireCaptchaForLogin bool
RequireExternalRegistrationCaptcha bool
Expand Down Expand Up @@ -182,11 +177,6 @@ func loadServiceFrom(rootCfg ConfigProvider) {
Service.EnableBasicAuth = sec.Key("ENABLE_BASIC_AUTHENTICATION").MustBool(true)
Service.EnablePasswordSignInForm = sec.Key("ENABLE_PASSWORD_SIGNIN_FORM").MustBool(true)
Service.EnablePasskeyAuth = sec.Key("ENABLE_PASSKEY_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()
Service.EnableCaptcha = sec.Key("ENABLE_CAPTCHA").MustBool(false)
Service.RequireCaptchaForLogin = sec.Key("REQUIRE_CAPTCHA_FOR_LOGIN").MustBool(false)
Service.RequireExternalRegistrationCaptcha = sec.Key("REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA").MustBool(Service.EnableCaptcha)
Expand Down
1 change: 1 addition & 0 deletions modules/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ func loadCommonSettingsFrom(cfg ConfigProvider) error {

loadOAuth2From(cfg)
loadSecurityFrom(cfg)
loadReverseProxyFrom(cfg)
if err := loadAttachmentFrom(cfg); err != nil {
return err
}
Expand Down
13 changes: 12 additions & 1 deletion options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3341,7 +3341,18 @@ config.repo_root_path = Repository Root Path
config.lfs_root_path = LFS Root Path
config.log_file_root_path = Log Path
config.script_type = Script Type
config.reverse_auth_user = Reverse Authentication User

config.reverseproxy_config = Reverse Proxy Configuration
config.reverseproxy_enable_auth = Enable Reverse Proxy Authentication
config.reverseproxy_enable_auth_api = Enable Reverse Proxy Authentication for API
config.reverseproxy_enable_auto_register = Enable Reverse Proxy Auto Registration
config.reverseproxy_enable_email = Enable Reverse Proxy Email
config.reverseproxy_enable_full_name = Enable Reverse Proxy Full Name
config.reverseproxy_auth_user = Reverse Authentication User
config.reverseproxy_auth_email = Reverse Authentication Email
config.reverseproxy_auth_full_name = Reverse Authentication Full Name
config.reverseproxy_limit = Reverse Proxy Limit
config.reverseproxy_trusted_proxies = Reverse Proxy Trusted Proxies

config.ssh_config = SSH Configuration
config.ssh_enabled = Enabled
Expand Down
2 changes: 1 addition & 1 deletion routers/api/packages/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.Context) {
}

func verifyAuth(r *web.Router, authMethods []auth.Method) {
if setting.Service.EnableReverseProxyAuth {
if setting.ReverseProxy.EnableAuth {
authMethods = append(authMethods, &auth.ReverseProxy{})
}
authGroup := auth.NewGroup(authMethods...)
Expand Down
4 changes: 2 additions & 2 deletions routers/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ func reqUsersExploreEnabled() 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 {
if ctx.IsSigned && setting.ReverseProxy.EnableAuthAPI && ctx.Data["AuthedMethod"].(string) == auth.ReverseProxyMethodName {
return
}
if !ctx.IsBasicAuth {
Expand Down Expand Up @@ -760,7 +760,7 @@ 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 {
if setting.ReverseProxy.EnableAuthAPI {
group.Add(&auth.ReverseProxy{})
}

Expand Down
4 changes: 2 additions & 2 deletions routers/common/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ func ProtocolMiddlewares() (handlers []any) {
handlers = append(handlers, ChiRoutePathHandler()) // make sure chi has correct paths
handlers = append(handlers, RequestContextHandler()) // prepare the context and panic recovery

if setting.ReverseProxyLimit > 0 && len(setting.ReverseProxyTrustedProxies) > 0 {
handlers = append(handlers, ForwardedHeadersHandler(setting.ReverseProxyLimit, setting.ReverseProxyTrustedProxies))
if setting.ReverseProxy.Limit > 0 && len(setting.ReverseProxy.TrustedProxies) > 0 {
handlers = append(handlers, ForwardedHeadersHandler(setting.ReverseProxy.Limit, setting.ReverseProxy.TrustedProxies))
}

if setting.IsRouteLogEnabled() {
Expand Down
4 changes: 2 additions & 2 deletions routers/web/admin/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ func Config(ctx *context.Context) {
ctx.Data["CustomRootPath"] = setting.CustomPath
ctx.Data["LogRootPath"] = setting.Log.RootPath
ctx.Data["ScriptType"] = setting.ScriptType
ctx.Data["ReverseProxyAuthUser"] = setting.ReverseProxyAuthUser
ctx.Data["ReverseProxyAuthEmail"] = setting.ReverseProxyAuthEmail

ctx.Data["ReverseProxy"] = setting.ReverseProxy

ctx.Data["SSH"] = setting.SSH
ctx.Data["LFS"] = setting.LFS
Expand Down
2 changes: 1 addition & 1 deletion routers/web/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func buildAuthGroup() *auth_service.Group {
group.Add(&auth_service.OAuth2{}) // FIXME: this should be removed and only applied in download and oauth related routers
group.Add(&auth_service.Basic{}) // FIXME: this should be removed and only applied in download and git/lfs routers

if setting.Service.EnableReverseProxyAuth {
if setting.ReverseProxy.EnableAuth {
group.Add(&auth_service.ReverseProxy{}) // reverse-proxy should before Session, otherwise the header will be ignored if user has login
}
group.Add(&auth_service.Session{})
Expand Down
16 changes: 8 additions & 8 deletions services/auth/reverseproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type ReverseProxy struct{}

// getUserName extracts the username from the "setting.ReverseProxyAuthUser" header
func (r *ReverseProxy) getUserName(req *http.Request) string {
return strings.TrimSpace(req.Header.Get(setting.ReverseProxyAuthUser))
return strings.TrimSpace(req.Header.Get(setting.ReverseProxy.AuthUser))
}

// Name represents the name of auth method
Expand Down Expand Up @@ -68,7 +68,7 @@ func (r *ReverseProxy) getUserFromAuthUser(req *http.Request) (*user_model.User,

// getEmail extracts the email from the "setting.ReverseProxyAuthEmail" header
func (r *ReverseProxy) getEmail(req *http.Request) string {
return strings.TrimSpace(req.Header.Get(setting.ReverseProxyAuthEmail))
return strings.TrimSpace(req.Header.Get(setting.ReverseProxy.AuthEmail))
}

// getUserFromAuthEmail extracts the username from the "setting.ReverseProxyAuthEmail" header
Expand All @@ -79,7 +79,7 @@ func (r *ReverseProxy) getEmail(req *http.Request) string {
// user object is returned (populated with the email found in header).
// Returns nil if header is empty or if "setting.EnableReverseProxyEmail" is disabled.
func (r *ReverseProxy) getUserFromAuthEmail(req *http.Request) *user_model.User {
if !setting.Service.EnableReverseProxyEmail {
if !setting.ReverseProxy.EnableEmail {
return nil
}
email := r.getEmail(req)
Expand Down Expand Up @@ -130,7 +130,7 @@ func (r *ReverseProxy) Verify(req *http.Request, w http.ResponseWriter, store Da

// isAutoRegisterAllowed checks if EnableReverseProxyAutoRegister setting is true
func (r *ReverseProxy) isAutoRegisterAllowed() bool {
return setting.Service.EnableReverseProxyAutoRegister
return setting.ReverseProxy.EnableAutoRegister
}

// newUser creates a new user object for the purpose of automatic registration
Expand All @@ -142,16 +142,16 @@ func (r *ReverseProxy) newUser(req *http.Request) *user_model.User {
}

email := gouuid.New().String() + "@localhost"
if setting.Service.EnableReverseProxyEmail {
webAuthEmail := req.Header.Get(setting.ReverseProxyAuthEmail)
if setting.ReverseProxy.EnableEmail {
webAuthEmail := req.Header.Get(setting.ReverseProxy.AuthEmail)
if len(webAuthEmail) > 0 {
email = webAuthEmail
}
}

var fullname string
if setting.Service.EnableReverseProxyFullName {
fullname = req.Header.Get(setting.ReverseProxyAuthFullName)
if setting.ReverseProxy.EnableFullName {
fullname = req.Header.Get(setting.ReverseProxy.AuthFullName)
}

user := &user_model.User{
Expand Down
33 changes: 31 additions & 2 deletions templates/admin/config.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,40 @@
<dd>{{.LogRootPath}}</dd>
<dt>{{ctx.Locale.Tr "admin.config.script_type"}}</dt>
<dd>{{.ScriptType}}</dd>
<dt>{{ctx.Locale.Tr "admin.config.reverse_auth_user"}}</dt>
<dd>{{.ReverseProxyAuthUser}}</dd>
</dl>
</div>

{{if or .ReverseProxy.EnableAuth .ReverseProxy.EnableAuthAPI}}
<h4 class="ui top attached header">
{{ctx.Locale.Tr "admin.config.reverseproxy_config"}}
</h4>
<div class="ui attached table segment">
<dl class="admin-dl-horizontal">
<dt>{{ctx.Locale.Tr "admin.config.reverseproxy_enable_auth"}}</dt>
<dd>{{.ReverseProxy.EnableAuth}}</dd>
<dt>{{ctx.Locale.Tr "admin.config.reverseproxy_enable_auth_api"}}</dt>
<dd>{{.ReverseProxy.EnableAuthAPI}}</dd>
<dt>{{ctx.Locale.Tr "admin.config.reverseproxy_enable_auto_register"}}</dt>
<dd>{{.ReverseProxy.EnableAutoRegister}}</dd>
<dt>{{ctx.Locale.Tr "admin.config.reverseproxy_enable_email"}}</dt>
<dd>{{.ReverseProxy.EnableEmail}}</dd>
<dt>{{ctx.Locale.Tr "admin.config.reverseproxy_enable_full_name"}}</dt>
<dd>{{.ReverseProxy.EnableFullName}}</dd>

<dt>{{ctx.Locale.Tr "admin.config.reverseproxy_auth_user"}}</dt>
<dd>{{.ReverseProxy.AuthUser}}</dd>
<dt>{{ctx.Locale.Tr "admin.config.reverseproxy_auth_email"}}</dt>
<dd>{{.ReverseProxy.AuthEmail}}</dd>
<dt>{{ctx.Locale.Tr "admin.config.reverseproxy_auth_full_name"}}</dt>
<dd>{{.ReverseProxy.AuthFullName}}</dd>
<dt>{{ctx.Locale.Tr "admin.config.reverseproxy_limit"}}</dt>
<dd>{{.ReverseProxy.Limit}}</dd>
<dt>{{ctx.Locale.Tr "admin.config.reverseproxy_trusted_proxies"}}</dt>
<dd>{{.ReverseProxy.TrustedProxies}}</dd>
</dl>
</div>
{{end}}

<h4 class="ui top attached header">
{{ctx.Locale.Tr "admin.config.ssh_config"}}
</h4>
Expand Down