// server/api/auth/logout.post.ts export default defineEventHandler(async (event) => { try { const config = useRuntimeConfig(); console.log('๐Ÿšช Logout handler called'); // Get the current session to retrieve tokens const sessionId = getCookie(event, 'user_session'); let idToken = null; if (sessionId) { try { const { getSession, deleteSession } = await import('~/server/utils/sessionStore'); const session = getSession(sessionId); if (session) { idToken = session.idToken; console.log('๐Ÿ”‘ ID token found in session:', !!idToken); // Delete session from store deleteSession(sessionId); } } catch (error) { console.warn('โš ๏ธ Could not retrieve session:', error); } } else { console.warn('โš ๏ธ No session cookie found'); } // Clear all auth-related cookies console.log('๐Ÿงน Clearing session cookies...'); deleteCookie(event, 'user_session'); deleteCookie(event, 'oauth_state'); // Also clear with different path variations to be thorough deleteCookie(event, 'user_session', { path: '/' }); deleteCookie(event, 'oauth_state', { path: '/' }); console.log('โœ… Session cleared successfully'); // Construct the Keycloak logout URL with proper parameters // IMPORTANT: The post_logout_redirect_uri must be registered in Keycloak client settings // Use custom logout URI from env if provided, otherwise use default const logoutPath = config.keycloakLogoutUri || `${config.keycloakIssuer}/protocol/openid-connect/logout`; const logoutUrl = new URL(logoutPath); // Debug: Log the authUrl and logout URI being used console.log('๐Ÿ”ง Using authUrl from config:', config.public.authUrl); if (config.keycloakLogoutUri) { console.log('๐Ÿ”ง Using custom logout URI from env:', config.keycloakLogoutUri); } else { console.log('๐Ÿ”ง Using default logout URI:', logoutPath); } // Build the redirect URI - must match what's configured in Keycloak // Use custom post-logout redirect URI from env if provided, otherwise use just the base URL // Using base URL (e.g., http://localhost:3005) is more likely to be whitelisted in Keycloak const postLogoutRedirectUri = config.postLogoutRedirectUri || config.public.authUrl; if (config.postLogoutRedirectUri) { console.log('๐Ÿ”ง Using custom post-logout redirect URI from env:', config.postLogoutRedirectUri); } else { console.log('๐Ÿ”ง Using base authUrl as post-logout redirect URI:', postLogoutRedirectUri); } // Add required parameters for proper Keycloak logout logoutUrl.searchParams.set('client_id', config.keycloakClientId); logoutUrl.searchParams.set('post_logout_redirect_uri', postLogoutRedirectUri); // If we have an ID token, add it for proper session termination // This ensures Keycloak properly terminates the SSO session if (idToken) { logoutUrl.searchParams.set('id_token_hint', idToken); console.log('๐Ÿ”‘ Added id_token_hint to logout URL'); } else { console.warn('โš ๏ธ No ID token available for logout hint - logout may not fully terminate Keycloak session'); } console.log('๐Ÿ”— Keycloak logout URL constructed:', logoutUrl.toString()); console.log('๐Ÿ“ Post-logout redirect URI:', postLogoutRedirectUri); console.log('โš ๏ธ Make sure this redirect URI is configured in Keycloak client settings!'); // Return the logout URL to the client for redirect // This approach gives better control to the client-side code return { success: true, logoutUrl: logoutUrl.toString(), message: 'Session cleared successfully' }; } catch (error: any) { console.error('โŒ Logout error:', error); console.error('โŒ Error stack:', error.stack); // Even if there's an error, try to provide a basic logout URL const config = useRuntimeConfig(); const postLogoutRedirectUri = config.postLogoutRedirectUri || config.public.authUrl; const logoutPath = config.keycloakLogoutUri || `${config.keycloakIssuer}/protocol/openid-connect/logout`; const fallbackLogoutUrl = new URL(logoutPath); fallbackLogoutUrl.searchParams.set('client_id', config.keycloakClientId); fallbackLogoutUrl.searchParams.set('post_logout_redirect_uri', postLogoutRedirectUri); console.warn('โš ๏ธ Using fallback logout URL due to error'); return { success: false, logoutUrl: fallbackLogoutUrl.toString(), error: 'Logout encountered an error, but providing fallback logout URL', message: error.message }; } });