111 lines
3.5 KiB
TypeScript
111 lines
3.5 KiB
TypeScript
// 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 ---
|