diff --git a/src/app/api/logout/route.ts b/src/app/api/logout/route.ts new file mode 100644 index 0000000..038687f --- /dev/null +++ b/src/app/api/logout/route.ts @@ -0,0 +1,45 @@ +import { NextResponse } from 'next/server'; + +const COOKIE_NAMES = [ + 'authjs.session-token', + 'authjs.csrf-token', + 'authjs.callback-url', + '__Secure-authjs.session-token', + '__Secure-authjs.callback-url', + '__Host-authjs.csrf-token', + 'next-auth.session-token', + 'next-auth.csrf-token', + 'next-auth.callback-url', + '__Secure-next-auth.session-token', + '__Secure-next-auth.callback-url', + '__Host-next-auth.csrf-token', +]; + +export async function POST() { + const response = NextResponse.json({ ok: true }); + + for (const name of COOKIE_NAMES) { + // Set with secure attributes (production) + response.cookies.set({ + name, + value: '', + path: '/', + maxAge: 0, + expires: new Date(0), + httpOnly: true, + secure: true, + sameSite: 'lax', + }); + } + + // Prevent caching of this response + response.headers.set('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); + response.headers.set('Pragma', 'no-cache'); + response.headers.set('Expires', '0'); + + return response; +} + +export async function GET() { + return POST(); +} diff --git a/src/app/logout/page.tsx b/src/app/logout/page.tsx index 3b43224..f4dcc13 100644 --- a/src/app/logout/page.tsx +++ b/src/app/logout/page.tsx @@ -33,15 +33,27 @@ export default function LogoutPage() { localStorage.removeItem('refreshToken'); localStorage.removeItem('user'); - // Call NextAuth signOut — canonical way to clear session cookie - // (uses the exact cookie name/attributes from cookies config in auth.ts) + // Call NextAuth signOut first (clears session via NextAuth's own logic) try { await signOut({ redirect: false }); } catch { // Continue even if signOut fails } - // Belt-and-suspenders: server action to nuke any remaining auth cookies + // Hit our explicit logout route handler — returns Set-Cookie headers + // that nuke ALL auth cookies. Route handlers are more reliable than + // server actions for cookie deletion in production. + try { + await fetch('/api/logout', { + method: 'POST', + credentials: 'include', + cache: 'no-store', + }); + } catch { + // Continue + } + + // Server action fallback try { await clearAuthCookies(); } catch {