auth flow
This commit is contained in:
parent
32f77425de
commit
ed199d7a00
@ -1,11 +1,13 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState, useRef } from "react";
|
||||||
import { clearAuthCookies } from "@/lib/session";
|
import { clearAuthCookies } from "@/lib/session";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|
||||||
export default function LoggedOut() {
|
export default function LoggedOut() {
|
||||||
const [sessionStatus, setSessionStatus] = useState<'checking' | 'cleared' | 'error'>('checking');
|
const [sessionStatus, setSessionStatus] = useState<'checking' | 'cleared' | 'error'>('checking');
|
||||||
|
const iframeRef = useRef<HTMLIFrameElement>(null);
|
||||||
|
const forceLogout = new URLSearchParams(window.location.search).get('forceLogout') === 'true';
|
||||||
|
|
||||||
// Listen for any messages from iframes
|
// Listen for any messages from iframes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -27,6 +29,18 @@ export default function LoggedOut() {
|
|||||||
// Additional browser storage clearing
|
// Additional browser storage clearing
|
||||||
console.log('Performing complete browser storage cleanup');
|
console.log('Performing complete browser storage cleanup');
|
||||||
|
|
||||||
|
// Add a hidden iframe to directly call Keycloak logout endpoint
|
||||||
|
// This ensures the server-side Keycloak session is properly terminated
|
||||||
|
if (process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER) {
|
||||||
|
console.log('Adding Keycloak logout iframe');
|
||||||
|
const keycloakBaseUrl = process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER;
|
||||||
|
const logoutEndpoint = `${keycloakBaseUrl}/protocol/openid-connect/logout`;
|
||||||
|
|
||||||
|
if (iframeRef.current) {
|
||||||
|
iframeRef.current.src = logoutEndpoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Try to get any user ID from localStorage or sessionStorage for server-side cleanup
|
// Try to get any user ID from localStorage or sessionStorage for server-side cleanup
|
||||||
let userId = '';
|
let userId = '';
|
||||||
try {
|
try {
|
||||||
@ -124,6 +138,8 @@ export default function LoggedOut() {
|
|||||||
'rc_token',
|
'rc_token',
|
||||||
'rc_uid',
|
'rc_uid',
|
||||||
'Meteor.loginToken',
|
'Meteor.loginToken',
|
||||||
|
'AUTH_SESSION_ID',
|
||||||
|
'AUTH_SESSION_ID_LEGACY',
|
||||||
...chunkedCookies
|
...chunkedCookies
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -136,6 +152,13 @@ export default function LoggedOut() {
|
|||||||
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=.${rootDomain}; SameSite=None; Secure;`;
|
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=.${rootDomain}; SameSite=None; Secure;`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Additional paths that Keycloak might use
|
||||||
|
['/auth', '/realms'].forEach(path => {
|
||||||
|
keycloakCookies.forEach(cookieName => {
|
||||||
|
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${path}; domain=${window.location.hostname}; SameSite=None; Secure;`;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Notify any parent windows/iframes
|
// Notify any parent windows/iframes
|
||||||
try {
|
try {
|
||||||
if (window.parent && window.parent !== window) {
|
if (window.parent && window.parent !== window) {
|
||||||
@ -165,6 +188,13 @@ export default function LoggedOut() {
|
|||||||
backgroundRepeat: 'no-repeat'
|
backgroundRepeat: 'no-repeat'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{/* Hidden iframe for direct Keycloak logout */}
|
||||||
|
<iframe
|
||||||
|
ref={iframeRef}
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
title="keycloak-logout"
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="w-full max-w-md p-8 bg-black/60 backdrop-blur-sm rounded-lg shadow-xl">
|
<div className="w-full max-w-md p-8 bg-black/60 backdrop-blur-sm rounded-lg shadow-xl">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<h2 className="text-3xl font-bold text-white mb-4">
|
<h2 className="text-3xl font-bold text-white mb-4">
|
||||||
@ -192,14 +222,14 @@ export default function LoggedOut() {
|
|||||||
|
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
<Link
|
<Link
|
||||||
href="/signin?signedOut=true"
|
href="/signin?fresh=true"
|
||||||
className="inline-block px-8 py-3 bg-white text-gray-800 rounded hover:bg-gray-100 transition-colors mb-4"
|
className="inline-block px-8 py-3 bg-white text-gray-800 rounded hover:bg-gray-100 transition-colors mb-4"
|
||||||
>
|
>
|
||||||
Sign In Again
|
Sign In Again
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<p className="text-white/60 text-sm mt-4">
|
<p className="text-white/60 text-sm mt-4">
|
||||||
Note: If you're automatically signed in again, try clearing your browser cookies or restarting your browser.
|
Note: You'll need to enter your credentials when signing in again.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -9,9 +9,57 @@ export default function SignIn() {
|
|||||||
const { data: session } = useSession();
|
const { data: session } = useSession();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const signedOut = searchParams.get('signedOut') === 'true';
|
const signedOut = searchParams.get('signedOut') === 'true';
|
||||||
|
const forceFreshLogin = searchParams.get('fresh') === 'true';
|
||||||
const [isRedirecting, setIsRedirecting] = useState(false);
|
const [isRedirecting, setIsRedirecting] = useState(false);
|
||||||
const [isFromLogout, setIsFromLogout] = useState(false);
|
const [isFromLogout, setIsFromLogout] = useState(false);
|
||||||
|
|
||||||
|
// Clear all Keycloak cookies when the fresh parameter is present
|
||||||
|
useEffect(() => {
|
||||||
|
if (forceFreshLogin) {
|
||||||
|
console.log('Fresh login requested, clearing all Keycloak cookies');
|
||||||
|
|
||||||
|
// Clear auth cookies to ensure a fresh login
|
||||||
|
clearAuthCookies();
|
||||||
|
|
||||||
|
// Extra cleanup for Keycloak-specific cookies with different paths
|
||||||
|
const keycloakCookies = [
|
||||||
|
'KEYCLOAK_SESSION',
|
||||||
|
'KEYCLOAK_IDENTITY',
|
||||||
|
'KEYCLOAK_REMEMBER_ME',
|
||||||
|
'KC_RESTART',
|
||||||
|
'AUTH_SESSION_ID',
|
||||||
|
'AUTH_SESSION_ID_LEGACY',
|
||||||
|
'JSESSIONID'
|
||||||
|
];
|
||||||
|
|
||||||
|
const domains = [
|
||||||
|
window.location.hostname,
|
||||||
|
`.${window.location.hostname}`,
|
||||||
|
window.location.hostname.split('.').slice(-2).join('.'),
|
||||||
|
`.${window.location.hostname.split('.').slice(-2).join('.')}`
|
||||||
|
];
|
||||||
|
|
||||||
|
// Clear each cookie with various paths and domains
|
||||||
|
keycloakCookies.forEach(cookieName => {
|
||||||
|
domains.forEach(domain => {
|
||||||
|
const paths = ['/', '/auth', '/realms'];
|
||||||
|
paths.forEach(path => {
|
||||||
|
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${path}; domain=${domain}; SameSite=None; Secure`;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Also check for chunked cookies
|
||||||
|
const cookies = document.cookie.split(';');
|
||||||
|
cookies.forEach(cookie => {
|
||||||
|
const cookieName = cookie.split('=')[0].trim();
|
||||||
|
if (/\.\d+$/.test(cookieName)) {
|
||||||
|
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; SameSite=None; Secure`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [forceFreshLogin]);
|
||||||
|
|
||||||
// If signedOut is true, make sure we clean up any residual sessions
|
// If signedOut is true, make sure we clean up any residual sessions
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (signedOut) {
|
if (signedOut) {
|
||||||
@ -33,8 +81,13 @@ export default function SignIn() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Only automatically sign in if not explicitly signed out and not coming from logout
|
// Only automatically sign in if:
|
||||||
if (!signedOut && !isFromLogout && !isRedirecting && !session) {
|
// - Not explicitly signed out
|
||||||
|
// - Not coming from logout
|
||||||
|
// - Not forcing a fresh login
|
||||||
|
// - Not already redirecting
|
||||||
|
// - No session exists
|
||||||
|
if (!signedOut && !isFromLogout && !forceFreshLogin && !isRedirecting && !session) {
|
||||||
setIsRedirecting(true);
|
setIsRedirecting(true);
|
||||||
console.log('Triggering automatic sign-in');
|
console.log('Triggering automatic sign-in');
|
||||||
// Add a small delay to avoid immediate redirect which can cause loops
|
// Add a small delay to avoid immediate redirect which can cause loops
|
||||||
@ -45,7 +98,7 @@ export default function SignIn() {
|
|||||||
|
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}
|
}
|
||||||
}, [signedOut, isRedirecting, isFromLogout, session]);
|
}, [signedOut, isRedirecting, isFromLogout, forceFreshLogin, session]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (session?.user && !session.user.nextcloudInitialized) {
|
if (session?.user && !session.user.nextcloudInitialized) {
|
||||||
@ -62,7 +115,14 @@ export default function SignIn() {
|
|||||||
}
|
}
|
||||||
}, [session]);
|
}, [session]);
|
||||||
|
|
||||||
const showManualLoginButton = signedOut || isFromLogout || isRedirecting;
|
const showManualLoginButton = signedOut || isFromLogout || isRedirecting || forceFreshLogin;
|
||||||
|
|
||||||
|
// Determine the button text based on the context
|
||||||
|
const buttonText = forceFreshLogin
|
||||||
|
? 'Sign In (Fresh Login)'
|
||||||
|
: signedOut
|
||||||
|
? 'Sign In Again'
|
||||||
|
: 'Sign In';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -91,13 +151,19 @@ export default function SignIn() {
|
|||||||
onClick={() => signIn("keycloak", { callbackUrl: "/" })}
|
onClick={() => signIn("keycloak", { callbackUrl: "/" })}
|
||||||
className="w-full bg-white text-gray-800 py-3 rounded hover:bg-gray-100 transition-colors"
|
className="w-full bg-white text-gray-800 py-3 rounded hover:bg-gray-100 transition-colors"
|
||||||
>
|
>
|
||||||
Sign In
|
{buttonText}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex items-center justify-center">
|
<div className="flex items-center justify-center">
|
||||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-white"></div>
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-white"></div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{(signedOut || forceFreshLogin) && (
|
||||||
|
<p className="text-white/70 text-sm mt-4">
|
||||||
|
You'll need to enter your credentials again for security reasons
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -35,7 +35,7 @@ export function SignOutHandler() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, attempt to sign out from NextAuth explicitly
|
// Then, attempt to sign out from NextAuth explicitly with force option
|
||||||
await signOut({ redirect: false });
|
await signOut({ redirect: false });
|
||||||
|
|
||||||
// Clear Rocket Chat authentication tokens
|
// Clear Rocket Chat authentication tokens
|
||||||
@ -67,7 +67,7 @@ export function SignOutHandler() {
|
|||||||
// Then clear all auth-related cookies to ensure we break any local sessions
|
// Then clear all auth-related cookies to ensure we break any local sessions
|
||||||
clearAuthCookies();
|
clearAuthCookies();
|
||||||
|
|
||||||
// Get Keycloak logout URL
|
// Get Keycloak logout URL with additional parameters to force session expiration
|
||||||
if (process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER) {
|
if (process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER) {
|
||||||
console.log('Preparing complete Keycloak logout');
|
console.log('Preparing complete Keycloak logout');
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ export function SignOutHandler() {
|
|||||||
const keycloakBaseUrl = process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER;
|
const keycloakBaseUrl = process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER;
|
||||||
const logoutEndpoint = `${keycloakBaseUrl}/protocol/openid-connect/logout`;
|
const logoutEndpoint = `${keycloakBaseUrl}/protocol/openid-connect/logout`;
|
||||||
|
|
||||||
// Create form for POST logout (more reliable)
|
// Create form for POST logout (more reliable than GET)
|
||||||
const form = document.createElement('form');
|
const form = document.createElement('form');
|
||||||
form.method = 'POST';
|
form.method = 'POST';
|
||||||
form.action = logoutEndpoint;
|
form.action = logoutEndpoint;
|
||||||
@ -100,7 +100,7 @@ export function SignOutHandler() {
|
|||||||
const redirectInput = document.createElement('input');
|
const redirectInput = document.createElement('input');
|
||||||
redirectInput.type = 'hidden';
|
redirectInput.type = 'hidden';
|
||||||
redirectInput.name = 'post_logout_redirect_uri';
|
redirectInput.name = 'post_logout_redirect_uri';
|
||||||
redirectInput.value = `${window.location.origin}/loggedout`;
|
redirectInput.value = `${window.location.origin}/loggedout?forceLogout=true`;
|
||||||
form.appendChild(redirectInput);
|
form.appendChild(redirectInput);
|
||||||
|
|
||||||
// Add logout_hint=server to explicitly request server-side session cleanup
|
// Add logout_hint=server to explicitly request server-side session cleanup
|
||||||
@ -109,6 +109,27 @@ export function SignOutHandler() {
|
|||||||
logoutHintInput.name = 'logout_hint';
|
logoutHintInput.name = 'logout_hint';
|
||||||
logoutHintInput.value = 'server';
|
logoutHintInput.value = 'server';
|
||||||
form.appendChild(logoutHintInput);
|
form.appendChild(logoutHintInput);
|
||||||
|
|
||||||
|
// Add state parameter with random value to prevent CSRF
|
||||||
|
const stateInput = document.createElement('input');
|
||||||
|
stateInput.type = 'hidden';
|
||||||
|
stateInput.name = 'state';
|
||||||
|
stateInput.value = Math.random().toString(36).substring(2);
|
||||||
|
form.appendChild(stateInput);
|
||||||
|
|
||||||
|
// Set initiate_login_uri parameter to force login screen on next login
|
||||||
|
const initiateLoginInput = document.createElement('input');
|
||||||
|
initiateLoginInput.type = 'hidden';
|
||||||
|
initiateLoginInput.name = 'initiate_login_uri';
|
||||||
|
initiateLoginInput.value = `${window.location.origin}/signin?fresh=true`;
|
||||||
|
form.appendChild(initiateLoginInput);
|
||||||
|
|
||||||
|
// Add UI locales parameter
|
||||||
|
const uiLocalesInput = document.createElement('input');
|
||||||
|
uiLocalesInput.type = 'hidden';
|
||||||
|
uiLocalesInput.name = 'ui_locales';
|
||||||
|
uiLocalesInput.value = 'fr';
|
||||||
|
form.appendChild(uiLocalesInput);
|
||||||
|
|
||||||
// Notify iframe parents before logging out
|
// Notify iframe parents before logging out
|
||||||
try {
|
try {
|
||||||
@ -120,17 +141,46 @@ export function SignOutHandler() {
|
|||||||
console.error('Error notifying parent of logout:', e);
|
console.error('Error notifying parent of logout:', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Completely remove all Keycloak session cookies before logout
|
||||||
|
// This helps prevent automatic re-login
|
||||||
|
const keycloakCookies = [
|
||||||
|
'KEYCLOAK_SESSION',
|
||||||
|
'KEYCLOAK_IDENTITY',
|
||||||
|
'KEYCLOAK_REMEMBER_ME',
|
||||||
|
'KC_RESTART',
|
||||||
|
'KEYCLOAK_SESSION_LEGACY',
|
||||||
|
'KEYCLOAK_IDENTITY_LEGACY',
|
||||||
|
'AUTH_SESSION_ID',
|
||||||
|
'AUTH_SESSION_ID_LEGACY',
|
||||||
|
'JSESSIONID'
|
||||||
|
];
|
||||||
|
|
||||||
|
const domains = [
|
||||||
|
window.location.hostname,
|
||||||
|
`.${window.location.hostname}`,
|
||||||
|
window.location.hostname.split('.').slice(-2).join('.'),
|
||||||
|
`.${window.location.hostname.split('.').slice(-2).join('.')}`
|
||||||
|
];
|
||||||
|
|
||||||
|
keycloakCookies.forEach(cookieName => {
|
||||||
|
domains.forEach(domain => {
|
||||||
|
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=${domain}; SameSite=None; Secure`;
|
||||||
|
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/realms/; domain=${domain}; SameSite=None; Secure`;
|
||||||
|
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/auth/; domain=${domain}; SameSite=None; Secure`;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Append to body and submit
|
// Append to body and submit
|
||||||
document.body.appendChild(form);
|
document.body.appendChild(form);
|
||||||
console.log('Submitting Keycloak logout form with server-side logout');
|
console.log('Submitting Keycloak logout form with server-side logout');
|
||||||
form.submit();
|
form.submit();
|
||||||
} else {
|
} else {
|
||||||
console.log('No Keycloak configuration found, performing simple redirect');
|
console.log('No Keycloak configuration found, performing simple redirect');
|
||||||
window.location.href = '/loggedout';
|
window.location.href = '/loggedout?forceLogout=true';
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error during logout:', error);
|
console.error('Error during logout:', error);
|
||||||
window.location.href = '/loggedout';
|
window.location.href = '/loggedout?forceLogout=true';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,27 +1,80 @@
|
|||||||
import { NextResponse } from 'next/server';
|
import { NextResponse } from 'next/server';
|
||||||
import type { NextRequest } from 'next/server';
|
import type { NextRequest } from 'next/server';
|
||||||
|
|
||||||
// Maximum cookie size in bytes (a bit less than 4KB to be safe)
|
// Maximum cookie size in bytes (even more conservative to prevent chunking issues)
|
||||||
const MAX_COOKIE_SIZE = 3800;
|
const MAX_COOKIE_SIZE = 3500;
|
||||||
|
|
||||||
// This middleware runs before any request
|
// This middleware runs before any request
|
||||||
export function middleware(request: NextRequest) {
|
export function middleware(request: NextRequest) {
|
||||||
// Force NextAuth environment variables at runtime
|
// Force NextAuth environment variables at runtime to prevent cookie chunking
|
||||||
process.env.NEXTAUTH_COOKIE_SIZE_LIMIT = MAX_COOKIE_SIZE.toString();
|
process.env.NEXTAUTH_COOKIE_SIZE_LIMIT = MAX_COOKIE_SIZE.toString();
|
||||||
|
|
||||||
// Set defaults for cookie security
|
// Disable cookie callbacks which can increase cookie size
|
||||||
process.env.NEXTAUTH_CALLBACK = 'false';
|
process.env.NEXTAUTH_CALLBACK = 'false';
|
||||||
process.env.NEXTAUTH_SESSION_STORE_SESSION_TOKEN = 'false';
|
process.env.NEXTAUTH_SESSION_STORE_SESSION_TOKEN = 'false';
|
||||||
process.env.NEXTAUTH_JWT_STORE_RAW_TOKEN = 'false';
|
process.env.NEXTAUTH_JWT_STORE_RAW_TOKEN = 'false';
|
||||||
|
|
||||||
// Continue with the request
|
// Check if this is a logout-related request
|
||||||
|
const url = request.nextUrl.pathname;
|
||||||
|
const isLogoutPath = url.includes('/signout') || url.includes('/loggedout');
|
||||||
|
const isSigninPath = url.includes('/signin');
|
||||||
|
const hasForceLogoutParam = request.nextUrl.searchParams.has('forceLogout');
|
||||||
|
|
||||||
|
if (isLogoutPath || hasForceLogoutParam) {
|
||||||
|
// On logout pages, we want to ensure cookies are cleaned up
|
||||||
|
const response = NextResponse.next();
|
||||||
|
|
||||||
|
// List of authentication-related cookies to clear on logout
|
||||||
|
const authCookies = [
|
||||||
|
'next-auth.session-token',
|
||||||
|
'next-auth.callback-url',
|
||||||
|
'next-auth.csrf-token',
|
||||||
|
'next-auth.pkce.code-verifier',
|
||||||
|
'__Secure-next-auth.session-token',
|
||||||
|
'__Host-next-auth.csrf-token'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Clear each cookie with appropriate settings
|
||||||
|
authCookies.forEach(cookieName => {
|
||||||
|
// Try to detect and clear chunked cookies too
|
||||||
|
for (let i = 0; i < 5; i++) {
|
||||||
|
const chunkName = i > 0 ? `${cookieName}.${i}` : cookieName;
|
||||||
|
|
||||||
|
// Clear with domain
|
||||||
|
if (process.env.NEXTAUTH_COOKIE_DOMAIN) {
|
||||||
|
response.cookies.delete({
|
||||||
|
name: chunkName,
|
||||||
|
domain: process.env.NEXTAUTH_COOKIE_DOMAIN,
|
||||||
|
path: '/'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also clear without domain
|
||||||
|
response.cookies.delete({
|
||||||
|
name: chunkName,
|
||||||
|
path: '/'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For the signin page with fresh=true param, pass a header indicating fresh login
|
||||||
|
if (isSigninPath && request.nextUrl.searchParams.get('fresh') === 'true') {
|
||||||
|
const response = NextResponse.next();
|
||||||
|
response.headers.set('X-Force-Fresh-Login', 'true');
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue with the request for all other paths
|
||||||
return NextResponse.next();
|
return NextResponse.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure the middleware to run on specific paths
|
// Configure the middleware to run on specific paths
|
||||||
export const config = {
|
export const config = {
|
||||||
matcher: [
|
matcher: [
|
||||||
// Apply to all routes except static files and api routes that aren't auth
|
// Apply to all routes except static files
|
||||||
'/((?!_next/static|_next/image|favicon.ico|public).*)',
|
'/((?!_next/static|_next/image|favicon.ico|public).*)',
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
Loading…
Reference in New Issue
Block a user