diff --git a/ui/litellm-dashboard/src/app/page.tsx b/ui/litellm-dashboard/src/app/page.tsx index 8a748849baa..9946cc53925 100644 --- a/ui/litellm-dashboard/src/app/page.tsx +++ b/ui/litellm-dashboard/src/app/page.tsx @@ -43,7 +43,7 @@ import ToolPoliciesView from "@/components/ToolPoliciesView"; import SpendLogsTable from "@/components/view_logs"; import ViewUserDashboard from "@/components/view_users"; import { ThemeProvider } from "@/contexts/ThemeContext"; -import { getCookie } from "@/utils/cookieUtils"; +import { clearTokenCookies, getCookie } from "@/utils/cookieUtils"; import { isJwtExpired } from "@/utils/jwtUtils"; import { buildLoginUrlWithReturn, consumeReturnUrl, normalizeUrlForCompare, storeReturnUrl } from "@/utils/returnUrlUtils"; import { formatUserRole, isAdminRole } from "@/utils/roles"; @@ -56,14 +56,8 @@ import { ConfigProvider, theme } from "antd"; function deleteCookie(name: string, path = "/") { // Best-effort client-side clear (works for non-HttpOnly cookies without Domain) document.cookie = `${name}=; Max-Age=0; Path=${path}`; - // Also clear the JS-set cookie at /ui (used to work around HttpOnly proxies) if (name === "token") { - document.cookie = `${name}=; Max-Age=0; Path=/ui`; - try { - sessionStorage.removeItem(name); - } catch { - // sessionStorage may be unavailable - } + clearTokenCookies(); } } diff --git a/ui/litellm-dashboard/src/utils/cookieUtils.ts b/ui/litellm-dashboard/src/utils/cookieUtils.ts index c212f3b0a3b..928f640fc2d 100644 --- a/ui/litellm-dashboard/src/utils/cookieUtils.ts +++ b/ui/litellm-dashboard/src/utils/cookieUtils.ts @@ -1,6 +1,17 @@ /** * Utility functions for managing cookies */ +import { serverRootPath } from "@/components/networking"; + +/** + * Returns the cookie path for the UI. + * Respects server_root_path so the cookie works when LiteLLM is + * deployed behind a subpath (e.g. /myapp/ui instead of /ui). + */ +function getUiCookiePath(): string { + const root = serverRootPath === "/" ? "" : serverRootPath; + return `${root}/ui`; +} /** * Clears the token cookie from both root and /ui paths @@ -16,7 +27,8 @@ export function clearTokenCookies() { // Clear with various combinations of path and SameSite // Include current path in case of custom server root path const currentPath = window.location.pathname; - const paths = ["/", "/ui"]; + const uiCookiePath = getUiCookiePath(); + const paths = ["/", uiCookiePath]; // Add the current path directory if it's different from root and /ui if (currentPath && currentPath !== "/" && !currentPath.startsWith("/ui")) { @@ -70,7 +82,8 @@ export function storeLoginToken(token: string) { // is readable by getCookie() via document.cookie. try { const secure = window.location.protocol === "https:" ? "; Secure" : ""; - document.cookie = `token=${encodeURIComponent(token)}; path=/ui; SameSite=Lax${secure}`; + const cookiePath = getUiCookiePath(); + document.cookie = `token=${encodeURIComponent(token)}; path=${cookiePath}; SameSite=Lax${secure}`; } catch { // cookie setting may fail in restrictive environments }