interface User { id: string email: string username: string name: string } interface AuthState { user: User | null authenticated: boolean } export const useCustomAuth = () => { const user = ref(null) const authenticated = ref(false) const loading = ref(true) // Check authentication status const checkAuth = async () => { try { loading.value = true const data = await $fetch('/api/auth/session') user.value = data.user authenticated.value = data.authenticated } catch (error) { console.error('[AUTH] Session check failed:', error) user.value = null authenticated.value = false } finally { loading.value = false } } // Login with Keycloak const login = () => { const authUrl = 'https://auth.portnimara.dev/realms/client-portal/protocol/openid-connect/auth?' + new URLSearchParams({ client_id: 'client-portal', redirect_uri: 'https://client.portnimara.dev/api/auth/keycloak/callback', response_type: 'code', scope: 'openid profile email', state: Math.random().toString(36).substring(2) }).toString() console.log('[AUTH] Redirecting to Keycloak login') navigateTo(authUrl, { external: true }) } // Logout const logout = async () => { try { await navigateTo('/api/auth/logout', { external: true }) } catch (error) { console.error('[AUTH] Logout failed:', error) } } // Initialize auth state on composable creation onMounted(() => { checkAuth() }) return { user: readonly(user), authenticated: readonly(authenticated), loading: readonly(loading), login, logout, checkAuth } }