feat: implement robust logout API route to clear all authentication cookies
This commit is contained in:
45
src/app/api/logout/route.ts
Normal file
45
src/app/api/logout/route.ts
Normal file
@@ -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();
|
||||||
|
}
|
||||||
@@ -33,15 +33,27 @@ export default function LogoutPage() {
|
|||||||
localStorage.removeItem('refreshToken');
|
localStorage.removeItem('refreshToken');
|
||||||
localStorage.removeItem('user');
|
localStorage.removeItem('user');
|
||||||
|
|
||||||
// Call NextAuth signOut — canonical way to clear session cookie
|
// Call NextAuth signOut first (clears session via NextAuth's own logic)
|
||||||
// (uses the exact cookie name/attributes from cookies config in auth.ts)
|
|
||||||
try {
|
try {
|
||||||
await signOut({ redirect: false });
|
await signOut({ redirect: false });
|
||||||
} catch {
|
} catch {
|
||||||
// Continue even if signOut fails
|
// 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 {
|
try {
|
||||||
await clearAuthCookies();
|
await clearAuthCookies();
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
Reference in New Issue
Block a user