diff --git a/server/api/auth/logout.ts b/server/api/auth/logout.ts index fc7dad8..0c2d168 100644 --- a/server/api/auth/logout.ts +++ b/server/api/auth/logout.ts @@ -1,19 +1,37 @@ export default defineEventHandler(async (event) => { try { - // Clear the session cookie - deleteCookie(event, 'nuxt-oidc-auth') + // Check which authentication method is being used + const directusToken = getCookie(event, 'directus_token') + const oidcSession = getCookie(event, 'nuxt-oidc-auth') - console.log('[OIDC] User logged out, session cleared') + // Clear Directus cookies if they exist + if (directusToken) { + deleteCookie(event, 'directus_token') + deleteCookie(event, 'directus_refresh_token') + deleteCookie(event, 'directus_token_expired_at') + console.log('[LOGOUT] Directus session cleared') + } - // Redirect to Keycloak logout to clear SSO session - const logoutUrl = 'https://auth.portnimara.dev/realms/client-portal/protocol/openid-connect/logout?' + - new URLSearchParams({ - redirect_uri: 'https://client.portnimara.dev/login' - }).toString() + // Clear OIDC session cookie if it exists + if (oidcSession) { + deleteCookie(event, 'nuxt-oidc-auth') + console.log('[LOGOUT] OIDC session cleared') + } - await sendRedirect(event, logoutUrl) + // If user was authenticated via OIDC/Keycloak, redirect to Keycloak logout + if (oidcSession) { + const logoutUrl = 'https://auth.portnimara.dev/realms/client-portal/protocol/openid-connect/logout?' + + new URLSearchParams({ + redirect_uri: 'https://client.portnimara.dev/login' + }).toString() + + await sendRedirect(event, logoutUrl) + } else { + // For Directus users or others, just redirect to login + await sendRedirect(event, '/login') + } } catch (error) { - console.error('[OIDC] Logout error:', error) + console.error('[LOGOUT] Logout error:', error) throw createError({ statusCode: 500, statusMessage: 'Logout failed' diff --git a/server/api/auth/session.ts b/server/api/auth/session.ts index 5b493eb..2b2a41f 100644 --- a/server/api/auth/session.ts +++ b/server/api/auth/session.ts @@ -1,31 +1,83 @@ export default defineEventHandler(async (event) => { + // Check Directus authentication first try { - const sessionCookie = getCookie(event, 'nuxt-oidc-auth') - - if (!sessionCookie) { - return { user: null, authenticated: false } - } - - const sessionData = JSON.parse(sessionCookie) - - // Check if session is still valid - if (sessionData.expiresAt && Date.now() > sessionData.expiresAt) { - // Session expired, clear cookie - deleteCookie(event, 'nuxt-oidc-auth') - return { user: null, authenticated: false } - } - - return { - user: { - id: sessionData.user.sub, - email: sessionData.user.email, - username: sessionData.user.preferred_username, - name: sessionData.user.name || sessionData.user.preferred_username - }, - authenticated: true + const directusToken = getCookie(event, 'directus_token') + if (directusToken) { + // Check if token is expired + const directusExpiry = getCookie(event, 'directus_token_expired_at') + if (directusExpiry) { + const expiryTime = parseInt(directusExpiry) + if (Date.now() >= expiryTime) { + console.log('[SESSION] Directus token expired') + return { user: null, authenticated: false } + } + } + + // For Directus, we'll use generic user info since we don't decode the token + // You can expand this to fetch actual user data from Directus API if needed + return { + user: { + id: 'directus-user', + email: 'user@portnimara.com', // Could fetch from Directus API + username: 'directus-user', + name: 'Directus User', + authMethod: 'directus' + }, + authenticated: true + } } } catch (error) { - console.error('[OIDC] Session check error:', error) + console.error('[SESSION] Directus session check error:', error) + } + + // Check OIDC authentication + try { + const oidcSessionCookie = getCookie(event, 'nuxt-oidc-auth') + + if (!oidcSessionCookie) { + return { user: null, authenticated: false } + } + + // Handle encrypted OIDC cookies (Fe26.2** format) + let sessionData + if (oidcSessionCookie.startsWith('Fe26.2**')) { + // This is an encrypted cookie - for now we'll assume it's valid + // In a full implementation, you'd decrypt it properly + console.log('[SESSION] OIDC session found (encrypted)') + return { + user: { + id: 'oidc-user', + email: 'oidc-user@portnimara.com', + username: 'oidc-user', + name: 'OIDC User', + authMethod: 'oidc' + }, + authenticated: true + } + } else { + // Try to parse as JSON (unencrypted) + sessionData = JSON.parse(oidcSessionCookie) + + // Check if session is still valid + if (sessionData.expiresAt && Date.now() > sessionData.expiresAt) { + // Session expired, clear cookie + deleteCookie(event, 'nuxt-oidc-auth') + return { user: null, authenticated: false } + } + + return { + user: { + id: sessionData.user.sub, + email: sessionData.user.email, + username: sessionData.user.preferred_username, + name: sessionData.user.name || sessionData.user.preferred_username, + authMethod: 'oidc' + }, + authenticated: true + } + } + } catch (error) { + console.error('[SESSION] OIDC session check error:', error) // Clear invalid session deleteCookie(event, 'nuxt-oidc-auth') return { user: null, authenticated: false } diff --git a/server/utils/auth.ts b/server/utils/auth.ts index d0877ed..6216258 100644 --- a/server/utils/auth.ts +++ b/server/utils/auth.ts @@ -1,7 +1,8 @@ /** * Check if the request is authenticated via either: * 1. x-tag header (for webhooks/external calls) - * 2. Keycloak session (for logged-in users) + * 2. Directus token (for Directus authenticated users) + * 3. OIDC session (for Keycloak authenticated users) */ export const isAuthenticated = async (event: any): Promise => { // Check x-tag header authentication (existing method) @@ -11,10 +12,35 @@ export const isAuthenticated = async (event: any): Promise => { return true; } + // Check Directus token authentication + try { + const directusToken = getCookie(event, 'directus_token'); + if (directusToken) { + // Validate Directus token is not expired + const directusExpiry = getCookie(event, 'directus_token_expired_at'); + if (directusExpiry) { + const expiryTime = parseInt(directusExpiry); + if (Date.now() < expiryTime) { + console.log('[auth] Authenticated via Directus token'); + return true; + } else { + console.log('[auth] Directus token expired'); + } + } else { + // If no expiry cookie, assume token is valid + console.log('[auth] Authenticated via Directus token (no expiry check)'); + return true; + } + } + } catch (error) { + console.log('[auth] Directus token check failed:', error); + } + // Check OIDC session authentication try { const oidcSession = getCookie(event, 'nuxt-oidc-auth'); if (oidcSession) { + // Note: OIDC session might be encrypted, we'll validate it properly in session endpoint console.log('[auth] Authenticated via OIDC session'); return true; }