litellm-mirror/ui/litellm-dashboard/src/utils/cookieUtils.ts
Ishaan Jaff 01a44a4e47
(UI) - Security Improvement, move to JWT Auth for Admin UI Sessions (#8995)
* (UI) - Improvements to session handling logic  (#8970)

* add cookieUtils

* use utils for clearing cookies

* on logout use clearTokenCookies

* ui use correct clearTokenCookies

* navbar show userEmail on UserID page

* add timestamp on token cookie

* update generate_authenticated_redirect_response

* use common getAuthToken

* fix clearTokenCookies

* fixes for get auth token

* fix invitation link sign in logic

* Revert "fix invitation link sign in logic"

This reverts commit 30e5308cb3.

* fix getAuthToken

* update setAuthToken

* fix ui session handling

* fix ui session handler

* bug fix stop generating LiteLLM Virtual keys for access

* working JWT insert into cookies

* use central place to build UI JWT token

* add _validate_ui_token

* fix ui session handler

* fix fetchWithCredentials

* check allowed routes for ui session tokens

* expose validate_session endpoint

* validate session endpoint

* call sso/session/validate

* getUISessionDetails

* ui move to getUISessionDetails

* /sso/session/validate

* fix cookie utils

* use getUISessionDetails

* use ui_session_id

* "/spend/logs/ui" in spend_tracking_routes

* working sign in JWT flow for proxy admin

* allow proxy admin to access ui routes

* use check_route_access

* update types

* update login method

* fixes to ui session handler

* working flow for admin and internal users

* fixes for invite links

* use JWTs for SSO sign in

* fix /invitation/new flow

* fix code quality checks

* fix _get_ui_session_token_from_cookies

* /organization/list

* ui sso sign in

* TestUISessionHandler

* TestUISessionHandler
2025-03-04 21:48:23 -08:00

81 lines
2.6 KiB
TypeScript

/**
* Utility functions for managing cookies
*/
/**
* Clears the token cookie from both root and /ui paths
*/
import { validateSession } from "../components/networking"
// Define the interface for the JWT token data
export interface JWTTokenData {
user_id: string;
user_email: string | null;
user_role: string;
login_method: string;
premium_user: boolean;
auth_header_name: string;
iss: string;
aud: string;
exp: number;
disabled_non_admin_personal_key_creation: boolean;
scopes: string[];
session_id: string; // ui session id currently in progress
}
export function clearTokenCookies() {
// Get the current domain
const domain = window.location.hostname;
// Clear with various combinations of path and SameSite
const paths = ['/', '/ui'];
const sameSiteValues = ['Lax', 'Strict', 'None'];
// Get all cookies
const allCookies = document.cookie.split("; ");
const tokenPattern = /^token_\d+$/;
// Find all token cookies
const tokenCookieNames = allCookies
.map(cookie => cookie.split("=")[0])
.filter(name => name === "token" || tokenPattern.test(name));
// Clear each token cookie with various combinations
tokenCookieNames.forEach(cookieName => {
paths.forEach(path => {
// Basic clearing
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${path};`;
// With domain
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${path}; domain=${domain};`;
// Try different SameSite values
sameSiteValues.forEach(sameSite => {
const secureFlag = sameSite === 'None' ? ' Secure;' : '';
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${path}; SameSite=${sameSite};${secureFlag}`;
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${path}; domain=${domain}; SameSite=${sameSite};${secureFlag}`;
});
});
});
console.log("After clearing cookies:", document.cookie);
}
export function setAuthToken(token: string) {
// Generate a token name with current timestamp
const currentTimestamp = Math.floor(Date.now() / 1000);
const tokenName = `token_${currentTimestamp}`;
// Set the cookie with the timestamp-based name
document.cookie = `${tokenName}=${token}; path=/; domain=${window.location.hostname};`;
}
export async function getUISessionDetails(): Promise<JWTTokenData> {
const validated_jwt_token = await validateSession();
if (validated_jwt_token?.data) {
return validated_jwt_token.data as JWTTokenData;
} else {
throw new Error("Invalid JWT token");
}
}