// server/api/users/last-access.get.ts // Get last access time from Keycloak Admin API for a specific user using access token from session export default defineEventHandler(async (event) => { console.log("🔍 Last access endpoint called"); const query = getQuery(event); const userId = query.userId as string; if (!userId) { throw createError({ statusCode: 400, statusMessage: "userId is required", }); } try { const config = useRuntimeConfig(); // Get access token from current user session let accessToken: string | null = null; try { const { getSessionFromCookie } = await import('~/server/utils/sessionStore'); const session = await getSessionFromCookie(event); if (session && session.accessToken) { accessToken = session.accessToken; } } catch (e) { console.warn("âš ī¸ No valid session found"); } if (!accessToken) { return { lastAccess: null }; } // Extract realm from issuer (e.g., "http://keycloak:8080/realms/sandbox" -> "sandbox") const issuerUrl = new URL(config.keycloakIssuer); const realm = issuerUrl.pathname.split('/').filter(Boolean).pop() || 'master'; // Get user sessions from Keycloak Admin API using access token const sessionsUrl = `${config.keycloakIssuer.replace('/realms/' + realm, '')}/admin/realms/${realm}/users/${userId}/sessions`; const sessionsResponse = await fetch(sessionsUrl, { method: 'GET', headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json', }, }); if (!sessionsResponse.ok) { // If user has no sessions or no permission, return null if (sessionsResponse.status === 404 || sessionsResponse.status === 403) { console.log(`â„šī¸ No sessions found or no permission for user ${userId}`); return { lastAccess: null }; } return { lastAccess: null }; } const sessions = await sessionsResponse.json() as any[]; if (!sessions || sessions.length === 0) { console.log(`â„šī¸ No active sessions for user ${userId}`); return { lastAccess: null }; } // Find the most recent session (highest lastAccess timestamp) let lastAccessTimestamp = 0; sessions.forEach(session => { if (session.lastAccess && session.lastAccess > lastAccessTimestamp) { lastAccessTimestamp = session.lastAccess; } }); // Convert from milliseconds to seconds (Unix timestamp) const lastAccess = lastAccessTimestamp > 0 ? Math.floor(lastAccessTimestamp / 1000) : null; console.log(`✅ Last access for user ${userId}: ${lastAccess ? new Date(lastAccess * 1000).toISOString() : 'Never'}`); return { lastAccess }; } catch (error: any) { console.error("❌ Error fetching last access from Keycloak:", error); // Return null instead of throwing error to allow graceful degradation return { lastAccess: null }; } });