mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-05-30 23:40:40 +02:00
[Bug]: OIDC login fails with "No session" behind reverse proxy — session cookie lost during redirect (Firefox bounce-tracking protection) #3264
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @miketangovictor on GitHub (Mar 16, 2026).
What happened?
OIDC authentication fails with a 400 No session error when logging in through an external identity provider (tested with Authentik). The failure is intermittent on Chrome but consistent on Firefox.
The root cause is a combination of two issues:
Missing trust proxy setting — Without app.set("trust proxy", 1), Express cannot correctly interpret X-Forwarded-* headers from the reverse proxy. This causes the session cookie to behave unpredictably (incorrect secure flag inference, unreliable sameSite enforcement).
Session cookie lost during OIDC redirect — Firefox's bounce-tracking protection (enabled by default since Firefox 109) strips cookies set during rapid cross-site redirects. The OIDC authorization flow redirects: ABS → Authentik → ABS callback. Firefox treats the intermediate hop as a bounce tracker and discards the session cookie before the callback route is hit. When /auth/openid/callback is reached, req.session[sessionKey] is empty, and ABS returns 400 No session with no recovery path. The session cookie also lacks sameSite: "lax" and maxAge, which contributes to cookie instability — without maxAge it is a session-scoped cookie (cleared when the tab closes or the browser considers the session ended), and without sameSite: "lax" behavior varies by browser.
What did you expect to happen?
OIDC login should complete successfully on Firefox when ABS is running behind a reverse proxy (nginx, Caddy, Cloudflare Tunnel, etc.) with an external OIDC provider such as Authentik, Authelia, or Keycloak. This is a common and well-documented deployment pattern. The OIDC callback should either preserve the session across the redirect chain or have a server-side fallback to recover state when the session cookie is not present at callback time.
Steps to reproduce the issue
Additional reproduction note: The failure is 100% consistent on Firefox when bounce-tracking protection is active. It can also be reproduced on Chrome by manually clearing the ABS session cookie immediately after the initial redirect to the identity provider (simulating what Firefox does automatically).
Audiobookshelf version
v2.33.0 (also confirmed on v2.32.1 and earlier)
How are you running audiobookshelf?
Docker
What OS is your Audiobookshelf server hosted from?
Linux
If the issue is being seen in the UI, what browsers are you seeing the problem on?
Firefox
Logs
Additional Notes
The fix involves three changes to the server:
const app = express()
app.set("trust proxy", 1) // Trust X-Forwarded-* from reverse proxy
// In expressSession cookie config:
cookie: {
secure: false,
sameSite: "lax", // Prevent cookie from being withheld on same-site redirects
maxAge: 86400000 // Persist cookie for 24h (not session-scoped)
}
OidcAuthStrategy.js — Persist web-flow state in openIdAuthSession as a server-side fallback:
// After req.session[sessionKey] = { state, code_verifier, ... } is set:
if (!isMobileFlow) {
this.openIdAuthSession.set(state, {
__webState: { state, max_age, response_type, code_verifier, mobile: undefined, sso_redirect_uri },
__callbackUrl: req.query.redirect_uri || req.query.callback || null
})
}
Auth.js — At the callback route, fall back to openIdAuthSession if session cookie is missing:
if (!req.session[sessionKey]) {
const stateParam = req.query.state
if (stateParam && this.oidcAuthStrategy.openIdAuthSession.has(stateParam)) {
const stored = this.oidcAuthStrategy.openIdAuthSession.get(stateParam)
if (stored.__webState) {
req.session[sessionKey] = stored.__webState
if (!req.cookies.auth_cb && stored.__callbackUrl) {
req.cookies.auth_cb = stored.__callbackUrl
}
this.oidcAuthStrategy.openIdAuthSession.delete(stateParam)
} else {
return res.status(400).send('No session')
}
} else {
return res.status(400).send('No session')
}
}
This fix has been running in production on ABS v2.32.1 and v2.33.0 with Authentik as the OIDC provider and Firefox as
the primary client, with no regressions observed. The openIdAuthSession map already exists in the codebase for
mobile-flow state — this reuses it for web-flow recovery.
Related: Issue #4630 ("re-login very often") may be partially caused by this same failure mode, as the symptom
(sporadic login failures) matches session cookie loss on Firefox.
@miketangovictor commented on GitHub (Mar 18, 2026):
Adding a comment here that when I ran into this issue I had Claude Code work through the solution and then create the bug submission. It appears that this is something that had been identified back with issue #4630 and the script that was written and included above did fix the issue, but curious if others have experienced this or if there is anything about this fix that would be problematic.