/** * Authentication composable using BFF (Backend for Frontend) pattern * Auth tokens are stored in HTTP-only cookies managed by Nitro server * Tenant context is stored in a readable cookie for client-side access */ export const useAuth = () => { const authMessageCookie = useCookie('authMessage') const tenantCookie = useCookie('routebox_tenant') const router = useRouter() // Reactive user state - populated from /api/auth/me const user = useState('auth_user', () => null) const isAuthenticated = useState('auth_is_authenticated', () => false) const isLoading = useState('auth_is_loading', () => false) /** * Check if user is logged in * Uses server-side session validation via /api/auth/me */ const isLoggedIn = () => { return isAuthenticated.value } /** * Login with email and password * Calls the Nitro BFF login endpoint which sets HTTP-only cookies */ const login = async (email: string, password: string) => { isLoading.value = true try { const response = await $fetch('/api/auth/login', { method: 'POST', body: { email, password }, }) if (response.success) { user.value = response.user isAuthenticated.value = true return { success: true, user: response.user } } return { success: false, error: 'Login failed' } } catch (error: any) { const message = error.data?.message || error.message || 'Login failed' return { success: false, error: message } } finally { isLoading.value = false } } /** * Logout user * Calls the Nitro BFF logout endpoint which clears HTTP-only cookies */ const logout = async () => { try { await $fetch('/api/auth/logout', { method: 'POST', }) } catch (error) { console.error('Logout error:', error) } // Clear local state user.value = null isAuthenticated.value = false // Set flash message for login page authMessageCookie.value = 'Logged out successfully' // Redirect to login page router.push('/login') } /** * Check current authentication status * Validates session with backend via Nitro BFF */ const checkAuth = async () => { isLoading.value = true try { const response = await $fetch('/api/auth/me', { method: 'GET', }) if (response.authenticated && response.user) { user.value = response.user isAuthenticated.value = true return true } } catch (error) { // Session invalid or expired user.value = null isAuthenticated.value = false } finally { isLoading.value = false } return false } /** * Get current user */ const getUser = () => { return user.value } /** * Get current tenant ID from cookie */ const getTenantId = () => { return tenantCookie.value } return { // State user, isAuthenticated, isLoading, // Methods isLoggedIn, login, logout, checkAuth, getUser, getTenantId, } }