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
5 changes: 5 additions & 0 deletions custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,11 @@ INTERNAL_TOKEN =
;; Name of cookie used to store authentication information.
;COOKIE_REMEMBER_NAME = gitea_incredible
;;
;; URL or path that Gitea should redirect users to *after* performing its own logout.
;; Use this, if needed, when authentication is handled by a reverse proxy or SSO.
;; Mellon example: REVERSE_PROXY_LOGOUT_REDIRECT = /mellon/logout?ReturnTo=/
;REVERSE_PROXY_LOGOUT_REDIRECT =
;;
;; Reverse proxy authentication header name of user name, email, and full name
;REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER
;REVERSE_PROXY_AUTHENTICATION_EMAIL = X-WEBAUTH-EMAIL
Expand Down
2 changes: 2 additions & 0 deletions modules/setting/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ var (
ReverseProxyAuthEmail string
ReverseProxyAuthFullName string
ReverseProxyLimit int
ReverseProxyLogoutRedirect string
ReverseProxyTrustedProxies []string
MinPasswordLength int
ImportLocalPaths bool
Expand Down Expand Up @@ -121,6 +122,7 @@ func loadSecurityFrom(rootCfg ConfigProvider) {
ReverseProxyAuthFullName = sec.Key("REVERSE_PROXY_AUTHENTICATION_FULL_NAME").MustString("X-WEBAUTH-FULLNAME")

ReverseProxyLimit = sec.Key("REVERSE_PROXY_LIMIT").MustInt(1)
ReverseProxyLogoutRedirect = sec.Key("REVERSE_PROXY_LOGOUT_REDIRECT").MustString("")
ReverseProxyTrustedProxies = sec.Key("REVERSE_PROXY_TRUSTED_PROXIES").Strings(",")
if len(ReverseProxyTrustedProxies) == 0 {
ReverseProxyTrustedProxies = []string{"127.0.0.0/8", "::1/128"}
Expand Down
6 changes: 5 additions & 1 deletion routers/web/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,11 @@ func SignOut(ctx *context.Context) {
})
}
HandleSignOut(ctx)
ctx.JSONRedirect(setting.AppSubURL + "/")
if setting.ReverseProxyLogoutRedirect != "" {
ctx.Redirect(setting.ReverseProxyLogoutRedirect)
return
}
ctx.Redirect(setting.AppSubURL + "/")
}

// SignUp render the register page
Expand Down
6 changes: 4 additions & 2 deletions templates/base/head_navbar.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
</div>

<div class="divider"></div>
<a class="item link-action" href data-url="{{AppSubUrl}}/user/logout">
<form id="logout-form" method="post" action="{{AppSubUrl}}/user/logout"></form>
<a class="item" onclick="document.getElementById('logout-form').submit();">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It’s not recommended to use an event handler in this style.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm open to suggestions. @silverwind, you wrote:

inline <form> to trigger the POST and change the link to a button with type=submit, so it works without JS.
Thought that does present a challenge in the styling because we don't have CSS to style a button like a link.

Could you help with styling a button?

{{svg "octicon-sign-out"}}
{{ctx.Locale.Tr "sign_out"}}
</a>
Expand Down Expand Up @@ -128,7 +129,8 @@
</a>
{{end}}
<div class="divider"></div>
<a class="item link-action" href data-url="{{AppSubUrl}}/user/logout">
<form id="logout-form" method="post" action="{{AppSubUrl}}/user/logout"></form>
<a class="item" onclick="document.getElementById('logout-form').submit();">
{{svg "octicon-sign-out"}}
{{ctx.Locale.Tr "sign_out"}}
</a>
Expand Down
31 changes: 30 additions & 1 deletion tests/integration/signout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"net/http"
"testing"

"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/tests"
)

Expand All @@ -16,7 +18,34 @@ func TestSignOut(t *testing.T) {
session := loginUser(t, "user2")

req := NewRequest(t, "POST", "/user/logout")
session.MakeRequest(t, req, http.StatusOK)
resp := session.MakeRequest(t, req, http.StatusSeeOther)

expected := "/"
loc := resp.Header().Get("Location")
if loc != expected {
t.Fatalf("expected redirect to %q, got %q", expected, loc)
}

// try to view a private repo, should fail
req = NewRequest(t, "GET", "/user2/repo2")
session.MakeRequest(t, req, http.StatusNotFound)
}

func TestSignOut_ReverseProxyLogoutRedirect(t *testing.T) {
defer tests.PrepareTestEnv(t)()

defer test.MockVariableValue(&setting.ReverseProxyLogoutRedirect, "/mellon/logout?ReturnTo=/")()

session := loginUser(t, "user2")

req := NewRequest(t, "POST", "/user/logout")
resp := session.MakeRequest(t, req, http.StatusSeeOther)

expected := "/mellon/logout?ReturnTo=/"
loc := resp.Header().Get("Location")
if loc != expected {
t.Fatalf("expected redirect to %q, got %q", expected, loc)
}

// try to view a private repo, should fail
req = NewRequest(t, "GET", "/user2/repo2")
Expand Down