Skip to content

Commit 29ae0fb

Browse files
committed
Implement logout redirection for reverse proxy setups
When authentication is handled externally by a reverse proxy, users can be redirected to an external logout URL or relative path defined on the reverse proxy.
1 parent 74060bb commit 29ae0fb

4 files changed

Lines changed: 28 additions & 0 deletions

File tree

custom/conf/app.example.ini

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,11 @@ INTERNAL_TOKEN =
460460
;; Name of cookie used to store authentication information.
461461
;COOKIE_REMEMBER_NAME = gitea_incredible
462462
;;
463+
;; URL or path that Gitea should redirect users to *after* performing its own logout.
464+
;; Use this, if needed, when authentication is handled by a reverse proxy or SSO.
465+
;; Mellon example: REVERSE_PROXY_LOGOUT_REDIRECT = /mellon/logout?ReturnTo=/
466+
;REVERSE_PROXY_LOGOUT_REDIRECT =
467+
;;
463468
;; Reverse proxy authentication header name of user name, email, and full name
464469
;REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER
465470
;REVERSE_PROXY_AUTHENTICATION_EMAIL = X-WEBAUTH-EMAIL

modules/setting/security.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ var (
3131
ReverseProxyAuthEmail string
3232
ReverseProxyAuthFullName string
3333
ReverseProxyLimit int
34+
ReverseProxyLogoutRedirect string
3435
ReverseProxyTrustedProxies []string
3536
MinPasswordLength int
3637
ImportLocalPaths bool
@@ -124,6 +125,7 @@ func loadSecurityFrom(rootCfg ConfigProvider) {
124125
ReverseProxyAuthFullName = sec.Key("REVERSE_PROXY_AUTHENTICATION_FULL_NAME").MustString("X-WEBAUTH-FULLNAME")
125126

126127
ReverseProxyLimit = sec.Key("REVERSE_PROXY_LIMIT").MustInt(1)
128+
ReverseProxyLogoutRedirect = sec.Key("REVERSE_PROXY_LOGOUT_REDIRECT").MustString("")
127129
ReverseProxyTrustedProxies = sec.Key("REVERSE_PROXY_TRUSTED_PROXIES").Strings(",")
128130
if len(ReverseProxyTrustedProxies) == 0 {
129131
ReverseProxyTrustedProxies = []string{"127.0.0.0/8", "::1/128"}

routers/web/auth/auth.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,9 @@ func buildSignOutRedirectURL(ctx *context.Context) string {
499499
return s
500500
}
501501
}
502+
if setting.ReverseProxyLogoutRedirect != "" {
503+
return setting.ReverseProxyLogoutRedirect
504+
}
502505
return setting.AppSubURL + "/"
503506
}
504507

tests/integration/signout_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"net/http"
88
"testing"
99

10+
"code.gitea.io/gitea/modules/setting"
1011
"code.gitea.io/gitea/modules/test"
1112
"code.gitea.io/gitea/tests"
1213

@@ -26,3 +27,20 @@ func TestSignOut(t *testing.T) {
2627
req = NewRequest(t, "GET", "/user2/repo2")
2728
session.MakeRequest(t, req, http.StatusNotFound)
2829
}
30+
31+
func TestSignOut_ReverseProxyLogoutRedirect(t *testing.T) {
32+
defer tests.PrepareTestEnv(t)()
33+
34+
defer test.MockVariableValue(&setting.ReverseProxyLogoutRedirect, "/mellon/logout?ReturnTo=/")()
35+
36+
session := loginUser(t, "user2")
37+
38+
req := NewRequest(t, "GET", "/user/logout")
39+
resp := session.MakeRequest(t, req, http.StatusSeeOther)
40+
41+
expected := "/mellon/logout?ReturnTo=/"
42+
loc := resp.Header().Get("Location")
43+
if loc != expected {
44+
t.Fatalf("expected redirect to %q, got %q", expected, loc)
45+
}
46+
}

0 commit comments

Comments
 (0)