export default defineNuxtRouteMiddleware(async (to) => { // Skip auth for SSR if (import.meta.server) return; // Check if auth is required (default true unless explicitly set to false) const isAuthRequired = to.meta.auth !== false; if (!isAuthRequired) { console.log('[MIDDLEWARE] Auth not required for route:', to.path); return; } // Skip auth check if we're already on the login page to prevent redirect loops if (to.path === '/login' || to.path.startsWith('/auth')) { return; } console.log('[MIDDLEWARE] Checking authentication for route:', to.path); // Use a cached auth state to avoid excessive API calls const nuxtApp = useNuxtApp(); const cacheKey = 'auth:session:cache'; const cacheExpiry = 30000; // 30 seconds cache // Check if we have a cached session const cachedSession = nuxtApp.payload.data[cacheKey]; const now = Date.now(); if (cachedSession && cachedSession.timestamp && (now - cachedSession.timestamp) < cacheExpiry) { console.log('[MIDDLEWARE] Using cached session'); if (cachedSession.authenticated && cachedSession.user) { return; } return navigateTo('/login'); } try { // Check Keycloak authentication via session API with timeout const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 5000); // 5 second timeout const sessionData = await $fetch('/api/auth/session', { signal: controller.signal, retry: 1, retryDelay: 500 }) as any; clearTimeout(timeout); // Cache the session data nuxtApp.payload.data[cacheKey] = { ...sessionData, timestamp: now }; console.log('[MIDDLEWARE] Session check result:', { authenticated: sessionData.authenticated, hasUser: !!sessionData.user, userId: sessionData.user?.id }); if (sessionData.authenticated && sessionData.user) { console.log('[MIDDLEWARE] User authenticated, allowing access'); return; } console.log('[MIDDLEWARE] No valid authentication found, redirecting to login'); return navigateTo('/login'); } catch (error: any) { console.error('[MIDDLEWARE] Auth check failed:', error); // If it's a network error or timeout, check if we have a recent cached session if (error.name === 'AbortError' || error.code === 'ECONNREFUSED') { console.log('[MIDDLEWARE] Network error, checking for recent cache'); const recentCache = nuxtApp.payload.data[cacheKey]; if (recentCache && recentCache.timestamp && (now - recentCache.timestamp) < 300000) { // 5 minutes console.log('[MIDDLEWARE] Using recent cache despite network error'); if (recentCache.authenticated && recentCache.user) { return; } } } return navigateTo('/login'); } });