import { Session } from "next-auth"; import { JWT } from "next-auth/jwt"; import { DefaultSession } from "next-auth"; export interface ServiceToken { token: string; userId: string; expiresAt: number; } export interface ExtendedSession extends DefaultSession { user: { id: string; name?: string | null; email?: string | null; image?: string | null; username: string; first_name: string; last_name: string; role: string[]; }; accessToken: string; refreshToken?: string; serviceTokens: { rocketChat?: ServiceToken; leantime?: ServiceToken; calendar?: ServiceToken; mail?: ServiceToken; [key: string]: ServiceToken | undefined; }; expires: string; } export interface ExtendedJWT extends JWT { accessToken?: string; refreshToken?: string; accessTokenExpires?: number; role?: string[]; username?: string; first_name?: string; last_name?: string; name?: string | null; email?: string | null; serviceTokens: { rocketChat?: ServiceToken; leantime?: ServiceToken; calendar?: ServiceToken; mail?: ServiceToken; [key: string]: ServiceToken | undefined; }; } export async function invalidateServiceTokens(session: ExtendedSession) { const serviceEndpoints = { rocketChat: `${process.env.NEXT_PUBLIC_IFRAME_PAROLE_URL?.split('/channel')[0]}/api/v1/logout`, leantime: `${process.env.LEANTIME_API_URL}/api/jsonrpc`, // Add other service endpoints as needed }; const invalidatePromises = Object.entries(session.serviceTokens).map(async ([service, token]) => { if (!token) return; try { const endpoint = serviceEndpoints[service as keyof typeof serviceEndpoints]; if (!endpoint) return; await fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', ...(service === 'rocketChat' ? { 'X-Auth-Token': token.token, 'X-User-Id': token.userId, } : {}), ...(service === 'leantime' ? { 'X-API-Key': process.env.LEANTIME_TOKEN!, } : {}), }, body: service === 'leantime' ? JSON.stringify({ jsonrpc: '2.0', method: 'leantime.rpc.auth.logout', id: 1 }) : undefined, }); } catch (error) { console.error(`Error invalidating ${service} token:`, error); } }); await Promise.all(invalidatePromises); } /** * Clears all authentication-related cookies from the browser */ export function clearAuthCookies() { // List of common auth-related cookies const authCookies = [ 'next-auth.session-token', 'next-auth.callback-url', 'next-auth.csrf-token', '__Secure-next-auth.session-token', '__Host-next-auth.csrf-token', 'next-auth.pkce.code_verifier', 'KEYCLOAK_SESSION', 'KEYCLOAK_IDENTITY', 'KEYCLOAK_REMEMBER_ME', 'KC_RESTART', 'AUTH_SESSION_ID', 'AUTH_SESSION_ID_LEGACY', 'JSESSIONID' ]; // Get all cookies to check for chunked auth cookies const cookies = document.cookie.split(';'); // Clear main auth cookies authCookies.forEach(cookieName => { document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; SameSite=None; Secure`; }); // Check for and clear any chunked cookies cookies.forEach(cookie => { const cookieName = cookie.split('=')[0].trim(); // Check for chunked cookies (they end with a number) if (cookieName.startsWith('next-auth.') && /\.\d+$/.test(cookieName)) { document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; SameSite=None; Secure`; } }); }