// server/api/auth/session.get.ts import type { SessionResponse } from '~/types/auth' // Helper function to safely decode the JWT payload (Access Token or ID Token) const decodeTokenPayload = (token: string | undefined): any | null => { if (!token) return null; try { // Tokens are base64 encoded and separated by '.' const parts = token.split("."); if (parts.length < 2) return null; // Not a valid JWT format const payloadBase64 = parts[1]; // Decode from base64 and parse the JSON // Note: Using Buffer.from is standard in Node.js server environments (like Nitro/H3) return JSON.parse(Buffer.from(payloadBase64, "base64").toString()); } catch (e) { console.error("❌ Failed to decode token payload:", e); return null; } }; // --- START OF THE SINGLE EXPORT DEFAULT HANDLER --- export default defineEventHandler(async (event) => { console.log("🔍 Session endpoint called"); const sessionId = getCookie(event, "user_session"); console.log("🍪 Session cookie exists:", !!sessionId); if (!sessionId) { console.log("❌ No session cookie found"); throw createError({ statusCode: 401, statusMessage: "No session cookie found", }); } try { // Get session from server-side store using session ID const { getSession } = await import('~/server/utils/sessionStore'); const session = getSession(sessionId); if (!session) { console.log("❌ Session not found or expired"); deleteCookie(event, "user_session"); throw createError({ statusCode: 401, statusMessage: "Session expired or invalid", }); } console.log("📋 Session retrieved from store successfully"); const isExpired = Date.now() > session.expiresAt; console.log("   Is Expired:", isExpired); // Check if the token has expired if (isExpired) { console.log("⏰ Session has expired, clearing cookie"); deleteCookie(event, "user_session"); throw createError({ statusCode: 401, statusMessage: "Session expired", }); } // Decode tokens and prepare the enhanced response data const idTokenPayload = decodeTokenPayload(session.idToken); const accessTokenPayload = decodeTokenPayload(session.accessToken); // Final response object - ensure it matches SessionResponse interface const sessionResponse: SessionResponse & { idToken?: any idTokenPayload?: any accessTokenPayload?: any fullSessionObject?: any status?: string } = { success: true, // Basic User Info user: session.user, // Raw Tokens (optional in SessionResponse) accessToken: session.accessToken, refreshToken: session.refreshToken, // Session Timestamps (optional in SessionResponse) expiresAt: session.expiresAt, // Additional debug fields (not in SessionResponse interface) idToken: session.idToken, idTokenPayload: idTokenPayload, accessTokenPayload: accessTokenPayload, fullSessionObject: session, status: "authenticated", }; console.log("✅ Session is valid, returning full session data"); return sessionResponse; } catch (parseError) { console.error("❌ Failed to parse session cookie:", parseError); // If JSON parsing fails or any other error occurs, the session is invalid deleteCookie(event, "user_session"); throw createError({ statusCode: 401, statusMessage: "Invalid session data", }); } }); // --- END OF THE SINGLE EXPORT DEFAULT HANDLER ---