git.iko.soy/typeable/oauth2-proxy
on master help sign in
fix: backend logout URL call on sign out (#3172) (#3352)

* Fix backend logout URL call on sign out (#3172) Signed-off-by: Vivek Sejpal <vsejpal@gmail.com> * doc: changelog entry for #3352 Signed-off-by: Jan Larwig <jan@larwig.com> --------- Signed-off-by: Vivek Sejpal <vsejpal@gmail.com> Signed-off-by: Jan Larwig <jan@larwig.com> Co-authored-by: Jan Larwig <jan@larwig.com>

commit75ff537915b84e1113446b3e5bacbc8b3ee5a741 authorVivek S Sejpal <vsejpal@users.noreply.github.com> dateFri 13 Mar 2026, 19:05 (7 months ago) parent8807573
3 files changed+44−2
CHANGELOG.md+2 oauthproxy.go+4−2 oauthproxy_test.go+38
CHANGELOG.md+2
@@ -8,6 +8,8 @@
88
99## Changes since v7.14.3
1010
11+- [#3352](https://github.com/oauth2-proxy/oauth2-proxy/pull/3352) fix: backend logout URL call on sign out (#3172)(@vsejpal)
12+
1113# V7.14.3
1214
1315## Release Highlights
oauthproxy.go+4−2
@@ -746,6 +746,10 @@ func (p *OAuthProxy) SignOut(rw http.ResponseWriter, req *http.Request) {
746746 p.ErrorPage(rw, req, http.StatusInternalServerError, err.Error())
747747 return
748748 }
749+ // Call backend logout before clearing the session so we still have the session
750+ // (and id_token) available to invoke the provider's logout endpoint
751+ p.backendLogout(rw, req)
752+
749753 err = p.ClearSessionCookie(rw, req)
750754 if err != nil {
751755 logger.Errorf("Error clearing session cookie: %v", err)
@@ -753,8 +757,6 @@ func (p *OAuthProxy) SignOut(rw http.ResponseWriter, req *http.Request) {
753757 return
754758 }
755759
756− p.backendLogout(rw, req)
757−
758760 http.Redirect(rw, req, redirect, http.StatusFound)
759761}
760762
oauthproxy_test.go+38
@@ -2028,6 +2028,44 @@ func Test_noCacheHeaders(t *testing.T) {
20282028 })
20292029}
20302030
2031+func TestSignOutCallsBackendLogoutURL(t *testing.T) {
2032+ const testIDToken = "test-id-token-12345"
2033+ var receivedURL string
2034+ backendLogoutServer := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
2035+ receivedURL = req.URL.String()
2036+ rw.WriteHeader(http.StatusOK)
2037+ }))
2038+ defer backendLogoutServer.Close()
2039+
2040+ opts := baseTestOptions()
2041+ opts.Providers[0].BackendLogoutURL = backendLogoutServer.URL + "/logout?id_token_hint={id_token}"
2042+ err := validation.Validate(opts)
2043+ require.NoError(t, err)
2044+
2045+ proxy, err := NewOAuthProxy(opts, func(string) bool { return true })
2046+ require.NoError(t, err)
2047+
2048+ // Save a session with IDToken so backend logout can use it
2049+ rw := httptest.NewRecorder()
2050+ req := httptest.NewRequest(http.MethodGet, "/", nil)
2051+ err = proxy.sessionStore.Save(rw, req, &sessions.SessionState{
2052+ Email: "user@example.com",
2053+ IDToken: testIDToken,
2054+ })
2055+ require.NoError(t, err)
2056+ cookie := rw.Header().Values("Set-Cookie")[0]
2057+
2058+ // Hit sign_out with the session cookie; backend logout should be called before session is cleared
2059+ signOutReq := httptest.NewRequest(http.MethodGet, "/oauth2/sign_out", nil)
2060+ signOutReq.Header.Set("Cookie", cookie)
2061+ rec := httptest.NewRecorder()
2062+ proxy.ServeHTTP(rec, signOutReq)
2063+
2064+ assert.Equal(t, http.StatusFound, rec.Code, "sign_out should redirect")
2065+ assert.Contains(t, receivedURL, "id_token_hint="+testIDToken,
2066+ "backend logout URL should have been called with id_token from session")
2067+}
2068+
20312069func baseTestOptions() *options.Options {
20322070 opts := options.NewOptions()
20332071 opts.Cookie.Secret = rawCookieSecret