feat: Centralize authentication redirects to middleware, remove client-side redirect logic, and refine logout process.
This commit is contained in:
@@ -1,7 +1,21 @@
|
||||
'use server';
|
||||
|
||||
import { signOut } from '@/auth';
|
||||
import { cookies } from 'next/headers';
|
||||
import { redirect } from 'next/navigation';
|
||||
|
||||
export async function logoutAction() {
|
||||
await signOut({ redirectTo: '/login' });
|
||||
// Force-delete all next-auth session cookies directly.
|
||||
// signOut() from next-auth was NOT clearing the httpOnly cookie reliably,
|
||||
// so we delete them explicitly using the cookies() API.
|
||||
const cookieStore = await cookies();
|
||||
|
||||
// Delete all possible next-auth v5 cookie names
|
||||
cookieStore.delete('authjs.session-token');
|
||||
cookieStore.delete('authjs.csrf-token');
|
||||
cookieStore.delete('authjs.callback-url');
|
||||
cookieStore.delete('__Secure-authjs.session-token');
|
||||
cookieStore.delete('__Secure-authjs.csrf-token');
|
||||
cookieStore.delete('__Secure-authjs.callback-url');
|
||||
|
||||
redirect('/login');
|
||||
}
|
||||
|
||||
@@ -40,8 +40,7 @@ export default function LogoutPage() {
|
||||
localStorage.removeItem('refreshToken');
|
||||
localStorage.removeItem('user');
|
||||
|
||||
// Manually clear next-auth cookies as fallback
|
||||
// next-auth v5 uses these cookie names:
|
||||
// Manually clear non-httpOnly next-auth cookies as fallback
|
||||
const cookieNames = [
|
||||
'authjs.session-token',
|
||||
'authjs.callback-url',
|
||||
@@ -59,13 +58,27 @@ export default function LogoutPage() {
|
||||
document.cookie = `${name}=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Secure`;
|
||||
});
|
||||
|
||||
// Use server action to properly clear session (redirects to /login)
|
||||
// Use server action to properly clear the httpOnly session cookie.
|
||||
// signOut() internally calls redirect() which throws NEXT_REDIRECT —
|
||||
// Next.js handles this automatically. We should NOT catch that error.
|
||||
// Only use fallback if the action truly fails (not a redirect throw).
|
||||
try {
|
||||
await logoutAction();
|
||||
} catch {
|
||||
// Server action redirect throws in Next.js — this is expected.
|
||||
// If it truly fails, the manual cookie clearing above ensures logout.
|
||||
// Fallback redirect:
|
||||
} catch (error: unknown) {
|
||||
// In Next.js App Router, redirect() throws an error with digest containing "NEXT_REDIRECT".
|
||||
// This is normal behavior — let it propagate so Next.js handles the redirect.
|
||||
const isRedirectError =
|
||||
error instanceof Error &&
|
||||
'digest' in error &&
|
||||
typeof (error as { digest?: string }).digest === 'string' &&
|
||||
(error as { digest: string }).digest.includes('NEXT_REDIRECT');
|
||||
|
||||
if (isRedirectError) {
|
||||
// Re-throw so Next.js handles the redirect properly
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Genuine error — use full page navigation as fallback
|
||||
window.location.href = '/login';
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user