From 0e45c2fa3339a6eb37543dd7ffa9e3d420e64c95 Mon Sep 17 00:00:00 2001 From: Philipp Kolberg Date: Fri, 31 Jul 2026 22:26:04 +0200 Subject: [PATCH] fix(auth): resolve OIDC logout URL before clearing auth state --- contexts/auth-context.tsx | 13 ++++++++++--- tests/lib/oidc-logout-source.test.js | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 tests/lib/oidc-logout-source.test.js diff --git a/contexts/auth-context.tsx b/contexts/auth-context.tsx index 84d8c70f..47168c4a 100644 --- a/contexts/auth-context.tsx +++ b/contexts/auth-context.tsx @@ -137,16 +137,23 @@ export function AuthProvider({ children }: { children: ReactNode }) { const logoutWithOidcRedirect = useCallback(async () => { const oidcSession = isValidOidcLogoutSession(oidcSessionStore) ? oidcSessionStore : undefined - logout() - if (!oidcSession) return false + if (!oidcSession) { + logout() + return false + } try { + // Build the URL before logout(), or DashboardAuthGuard redirects to login before this navigation runs. const { configManager } = await import("@/lib/config") const config = await configManager.loadConfig() - window.location.href = buildOidcLogoutUrl(config.serverHost, oidcSession.logoutToken) + const logoutUrl = buildOidcLogoutUrl(config.serverHost, oidcSession.logoutToken) + + logout() + window.location.href = logoutUrl return true } catch { + logout() return false } }, [oidcSessionStore, logout]) diff --git a/tests/lib/oidc-logout-source.test.js b/tests/lib/oidc-logout-source.test.js new file mode 100644 index 00000000..f1859eec --- /dev/null +++ b/tests/lib/oidc-logout-source.test.js @@ -0,0 +1,16 @@ +import test from "node:test" +import assert from "node:assert/strict" +import fs from "node:fs" + +const source = fs.readFileSync("contexts/auth-context.tsx", "utf8") + +test("OIDC federated logout builds its destination before clearing auth state", () => { + assert.match( + source, + /const logoutUrl = buildOidcLogoutUrl\(config\.serverHost, oidcSession\.logoutToken\)\s*\n\s*logout\(\)\s*\n\s*window\.location\.href = logoutUrl/, + ) +}) + +test("OIDC federated logout does not clear auth state before awaiting config", () => { + assert.doesNotMatch(source, /logout\(\)\s*\n\s*if \(!oidcSession\) return false/) +})