"use client"; import { useEffect } from "react"; import { useSession, signOut } from "next-auth/react"; import { MainNav } from "@/components/main-nav"; import { Footer } from "@/components/footer"; import { AuthCheck } from "@/components/auth/auth-check"; import { Toaster } from "@/components/ui/toaster"; import { useBackgroundImage } from "@/components/background-switcher"; import { clearAuthCookies, clearKeycloakCookies } from "@/lib/session"; interface LayoutWrapperProps { children: React.ReactNode; isSignInPage: boolean; isAuthenticated: boolean; } export function LayoutWrapper({ children, isSignInPage, isAuthenticated }: LayoutWrapperProps) { const { currentBackground, changeBackground } = useBackgroundImage(); const { data: session } = useSession(); // Global listener for logout messages from iframe applications useEffect(() => { if (isSignInPage) return; // Don't listen on signin page const handleMessage = async (event: MessageEvent) => { // Security: Validate message origin (in production, check against known iframe URLs) // For now, we accept messages from any origin but validate the message structure // Check if message is a logout request from iframe if (event.data && typeof event.data === 'object') { if (event.data.type === 'KEYCLOAK_LOGOUT' || event.data.type === 'LOGOUT') { console.log('Received logout request from iframe application, triggering dashboard logout'); try { // Mark logout in progress sessionStorage.setItem('just_logged_out', 'true'); document.cookie = 'logout_in_progress=true; path=/; max-age=60'; // Clear cookies clearAuthCookies(); clearKeycloakCookies(); // Sign out from NextAuth await signOut({ callbackUrl: '/signin?logout=true', redirect: false }); // Call Keycloak logout if we have ID token const keycloakIssuer = process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER; const idToken = session?.idToken; if (keycloakIssuer && idToken) { const keycloakLogoutUrl = new URL( `${keycloakIssuer}/protocol/openid-connect/logout` ); keycloakLogoutUrl.searchParams.append( 'post_logout_redirect_uri', window.location.origin + '/signin?logout=true' ); keycloakLogoutUrl.searchParams.append( 'id_token_hint', idToken ); // Add kc_action=LOGOUT to ensure SSO session is cleared keycloakLogoutUrl.searchParams.append( 'kc_action', 'LOGOUT' ); window.location.replace(keycloakLogoutUrl.toString()); } else { // Fallback: redirect to signin window.location.replace('/signin?logout=true'); } } catch (error) { console.error('Error handling iframe logout:', error); window.location.replace('/signin?logout=true'); } } } }; window.addEventListener('message', handleMessage); return () => { window.removeEventListener('message', handleMessage); }; }, [isSignInPage, session]); return ( {!isSignInPage && isAuthenticated && }
{children}
{!isSignInPage && isAuthenticated &&