export default defineNuxtPlugin(() => { // Only run on client side if (import.meta.server) return const nuxtApp = useNuxtApp() const toast = useToast() // Global error handler for API requests nuxtApp.hook('app:error', (error: any) => { console.error('[AUTH_ERROR_HANDLER] Application error:', error) // Handle authentication errors if (error.statusCode === 401 || error.statusCode === 403) { handleAuthError(error) } }) // Intercept $fetch errors globally const originalFetch = globalThis.$fetch globalThis.$fetch = $fetch.create({ onResponseError({ response }) { console.log('[AUTH_ERROR_HANDLER] Response error:', { status: response.status, url: response.url, statusText: response.statusText }) // Handle authentication errors (401, 403) if (response.status === 401 || response.status === 403) { handleAuthError({ statusCode: response.status, statusMessage: response.statusText, data: response._data }) } // Handle 404 errors that might be auth-related if (response.status === 404 && isProtectedRoute()) { console.warn('[AUTH_ERROR_HANDLER] 404 on protected route, may be auth-related') // Check if session is still valid checkAndHandleSession() } } }) const handleAuthError = async (error: any) => { console.error('[AUTH_ERROR_HANDLER] Authentication error detected:', error) // Clear all auth-related caches clearAuthCaches() // Only show toast and redirect if we're not already on the login page const route = useRoute() if (route.path !== '/login' && !route.path.startsWith('/auth')) { toast.error('Your session has expired. Please log in again.') // Delay navigation slightly to ensure toast is visible setTimeout(() => { navigateTo('/login') }, 500) } } const clearAuthCaches = () => { console.log('[AUTH_ERROR_HANDLER] Clearing authentication caches') // Clear Nuxt app payload caches if (nuxtApp.payload.data) { delete nuxtApp.payload.data['auth:session:cache'] delete nuxtApp.payload.data.authState } // Clear session cookie const sessionCookie = useCookie('nuxt-oidc-auth') sessionCookie.value = null } const isProtectedRoute = () => { const route = useRoute() // Check if current route requires authentication return route.meta.auth !== false && !route.path.startsWith('/login') && !route.path.startsWith('/auth') } const checkAndHandleSession = async () => { try { // Force a fresh session check without cache const response = await fetch('/api/auth/session', { headers: { 'Cache-Control': 'no-cache', 'Pragma': 'no-cache' } }) if (!response.ok) { throw new Error(`Session check failed: ${response.status}`) } const sessionData = await response.json() if (!sessionData.authenticated) { handleAuthError({ statusCode: 401, statusMessage: 'Session expired' }) } } catch (error) { console.error('[AUTH_ERROR_HANDLER] Failed to check session:', error) handleAuthError({ statusCode: 401, statusMessage: 'Session check failed' }) } } // Expose clearAuthCaches for manual use nuxtApp.provide('clearAuthCaches', clearAuthCaches) })