Repository navigation
[BUG] ZorxAuth: Remember Me duration is lost on the SSO gateway redirect to the session-set URL #1315
Description
Describe the bug
ZorxAuth's "Remember Me" checkbox only affects the first, interactive login. Whenever the user is already authenticated at the auth gateway (the "skip the login step" fast path), the gateway redirects to the session set URL without the remember_me parameter. The visited host therefore issues zr_xauth_session with the plain Cookie Duration and thereby overwrites a previously issued long-lived cookie on that host. Net effect: "Remember Me" seems to be ignored and sessions fall back to Cookie Duration.
This is not a version-specific bug and upgrading does not help. I verified on current main: the fast-path redirect in handleAuthPage is byte-identical to the code quoted below, and none of the commits that touched gateway.go / routers.go after the module was introduced changed the remember-me handling (last check: v3.3.5-rc1, merged 2026-09-16). All line numbers below refer to current main; the stable release numbers are given in brackets for reference. The module itself was added in v3.3.2-rc2 (PR #1055) - that is only the reporter's deployment, see the host environment section. I could not find an existing issue/PR/discussion covering this.
To Reproduce
Setup: Zoraxy Auth with Auth Gateway enabled, two protected hosts using the same SSO (e.g. app-a.example.com, app-b.example.com).
- Open
app-a.example.com, log in and check "Remember Me". - DevTools → Application → Cookies →
zr_xauth_sessiononapp-a.example.com:Max-Ageequals the configured "Cookie Duration (seconds) - Remember Me" value (e.g. 34560000). Correct so far. - Open
app-b.example.comin the same browser (no cookie for that host yet; gateway cookie is still valid) → the gateway takes its fast path. - DevTools on
app-b.example.com: the redirect is
…/.wellknown/zorxauth/session/set?session_id=…&redirect=…-remember_meis missing, so the resultingzr_xauth_sessionhasMax-Age=Cookie Duration(e.g. 3600).
The same happens on a host the user has visited before, as soon as its cookie is gone while the gateway cookie is still valid (delete only the app cookie, keep the gateway cookie, reload): the host cookie is re-issued with the short duration.
Expected behavior
"Remember Me" should apply to every session-set redirect, not just to the interactive login. The session cookie of the visited host should get Cookie Duration (seconds) - Remember Me.
Screenshots
N/A - the effect is visible in Browser DevTools (Application → Cookies → zr_xauth_session → Max-Age per host).
Browser (if it is a bug appears on the UI section of the system):
- OS: Windows 10
- Browser: Google Chrome
- Version: 153.0.8010.53
Host Environment (please complete following information, DO NOT REMOVE ANY FIELD(S)):
- Arch: amd64
- Device: VPS
- OS: Debian 13
- Version: 13 (trixie)
- Are you using Docker? (yes / no): no
- Docker Version (fill in "N/A" for native deployment): N/A
- Zoraxy Version: 3.3.2 (deployment I reproduced it on; the same code path is present in v3.3.5-rc1 /
main)
Supplementary links
#1055 (v3.3.2-rc2, introduced the ZorxAuth SSO module)
Additional context
Root cause - only the interactive login path forwards the flag:
- the login page (
POST /login→auth.html) buildssessionSetURL?session_id=…&redirect=…&remember_me=<data.rememberMe>and works. - the gateway fast path (already authenticated at the gateway) builds the redirect server side and never carries it:
// src/mod/auth/sso/zorxauth/gateway.go, handleAuthPage
// main / v3.3.5-rc1: line 250 [stable v3.3.2: line 220]
sessionSetURL := fmt.Sprintf("%s://%s/%s?session_id=%s&redirect=%s",
targetProtocol, hostWithPort,
strings.TrimPrefix(gs.router.Options.SSOSessionSetURL, "/"),
sessionId, url.QueryEscape(redirectURL))// src/mod/auth/sso/zorxauth/routers.go, handleSessionSetCallback
// main: line 144 [v3.3.2: line 148]
rememberMe := strings.EqualFold(r.URL.Query().Get("remember_me"), "true") || r.URL.Query().Get("remember_me") == "on"
cookieDuration := ar.Options.CookieDuration
if rememberMe { cookieDuration = ar.Options.CookieDurationRememberMe }…so rememberMe is false and MaxAge: cookieDuration (routers.go - main: line 180 [v3.3.2: line 184]) writes the short duration into the host cookie (same cookie name, same host → overwrite).
In addition, the fast path renews the gateway session with the plain CookieDuration (gateway.go - main: line 229 [v3.3.2: line 199]), because GatewaySession does not store the flag at all:
type GatewaySession struct {
Username string
Expiry time.Time
}Related observations in the same code path:
handleLoginhas no fallback forcookie_duration_remember_me <= 0whilehandleSessionSetCallbackdoes (routers.go - main: line 149 [v3.3.2: line 153]). With0, the gateway writesMaxAge: 0(plain session cookie) andtime.AfterFunc(0, …)(gateway.go - main: line 451 [v3.3.2: line 390]) removes the session from the store immediately → the user is bounced back to the login page. The admin UI would still show the default 604800 (settings.go - main/v3.3.2: lines 26-28).- The passkey login path (
passkey.go- main: line 479) never reads a remember-me flag, so passkey logins can only ever get the short duration. - For the record, the cookie itself is written as
Max-Age = <configured seconds>(noExpires, no scaling), so2592000yields exactly 30 days in Chromium - the browser side is not the problem; Chromium caps at 400 days.
Suggested fix: store the flag in the gateway session and reuse it for the renewal and for the session-set redirect (GatewaySession.RememberMe bool, set in handleLogin, then ...&remember_me=%t", …, rememberMe in the fast path).
Workaround until then: set Cookie Duration to the desired long value, since the fast path always uses that one.
I have a working patch for current main (applies with git apply -p1; go build / go vet / gofmt clean, plus a regression test asserting remember_me=true in the fast-path redirect). Happy to open a PR if you would like it fixed that way - just say the word.
Activity