mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
fix(ui): use shared getCookie in page.tsx and user_dashboard.tsx
Replace local getCookie functions in page.tsx and user_dashboard.tsx with the shared one from cookieUtils that has the sessionStorage fallback. Without this, the HttpOnly cookie fix was incomplete — page.tsx (the dashboard entry point) could not read the token, causing the redirect loop to persist. Also scope the sessionStorage fallback to the "token" key only, and clear sessionStorage in page.tsx deleteCookie. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
461cf00408
commit
523d1c388f
4 changed files with 14 additions and 19 deletions
|
|
@ -43,6 +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 { isJwtExpired } from "@/utils/jwtUtils";
|
||||
import { buildLoginUrlWithReturn, consumeReturnUrl, normalizeUrlForCompare, storeReturnUrl } from "@/utils/returnUrlUtils";
|
||||
import { formatUserRole, isAdminRole } from "@/utils/roles";
|
||||
|
|
@ -52,21 +53,14 @@ import { useSearchParams } from "next/navigation";
|
|||
import { Suspense, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { ConfigProvider, theme } from "antd";
|
||||
|
||||
function getCookie(name: string) {
|
||||
// Safer cookie read + decoding; handles '=' inside values
|
||||
const match = document.cookie.split("; ").find((row) => row.startsWith(name + "="));
|
||||
if (!match) return null;
|
||||
const value = match.slice(name.length + 1);
|
||||
try {
|
||||
return decodeURIComponent(value);
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
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}`;
|
||||
try {
|
||||
sessionStorage.removeItem(name);
|
||||
} catch {
|
||||
// sessionStorage may be unavailable
|
||||
}
|
||||
}
|
||||
|
||||
interface ProxySettings {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
"use client";
|
||||
import { clearTokenCookies } from "@/utils/cookieUtils";
|
||||
import { clearTokenCookies, getCookie } from "@/utils/cookieUtils";
|
||||
import { Col, Grid } from "@tremor/react";
|
||||
import { Typography } from "antd";
|
||||
import { jwtDecode } from "jwt-decode";
|
||||
|
|
@ -35,11 +35,7 @@ export type UserInfo = {
|
|||
spend: number;
|
||||
};
|
||||
|
||||
function getCookie(name: string) {
|
||||
console.log("COOKIES", document.cookie);
|
||||
const cookieValue = document.cookie.split("; ").find((row) => row.startsWith(name + "="));
|
||||
return cookieValue ? cookieValue.split("=")[1] : null;
|
||||
}
|
||||
|
||||
|
||||
interface UserDashboardProps {
|
||||
userID: string | null;
|
||||
|
|
|
|||
|
|
@ -188,5 +188,10 @@ describe("cookieUtils", () => {
|
|||
sessionStorage.setItem("token", "session-value");
|
||||
expect(getCookie("token")).toBe("cookie-value");
|
||||
});
|
||||
|
||||
it("should not fall back to sessionStorage for non-token keys", () => {
|
||||
sessionStorage.setItem("other", "other-value");
|
||||
expect(getCookie("other")).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ export function getCookie(name: string) {
|
|||
}
|
||||
// Fallback to sessionStorage — covers the case where a reverse proxy
|
||||
// added HttpOnly to the server-set cookie, making it invisible to JS.
|
||||
if (typeof window !== "undefined") {
|
||||
if (name === "token" && typeof window !== "undefined") {
|
||||
try {
|
||||
return sessionStorage.getItem(name);
|
||||
} catch {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue