diff --git a/admin-web/app/login/page.tsx b/admin-web/app/login/page.tsx index d38bacc..1d78f84 100644 --- a/admin-web/app/login/page.tsx +++ b/admin-web/app/login/page.tsx @@ -43,8 +43,8 @@ export default function LoginPage() { throw new Error("Not authorized as admin"); } - router.push("/"); - router.refresh(); + // Force a full page reload to ensure middleware picks up the session + window.location.href = "/"; } catch (err) { setError(err instanceof Error ? err.message : "Login failed"); } finally { diff --git a/admin-web/middleware.ts b/admin-web/middleware.ts index f42a481..7fbbebb 100644 --- a/admin-web/middleware.ts +++ b/admin-web/middleware.ts @@ -2,10 +2,8 @@ import { createServerClient } from '@supabase/ssr' import { NextResponse, type NextRequest } from 'next/server' export async function middleware(request: NextRequest) { - let response = NextResponse.next({ - request: { - headers: request.headers, - }, + let supabaseResponse = NextResponse.next({ + request, }) const supabase = createServerClient( @@ -13,41 +11,58 @@ export async function middleware(request: NextRequest) { process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { cookies: { - get(name: string) { - return request.cookies.get(name)?.value + getAll() { + return request.cookies.getAll() }, - set(name: string, value: string, options: any) { - request.cookies.set({ name, value, ...options }) - response = NextResponse.next({ - request: { headers: request.headers }, + setAll(cookiesToSet) { + cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value)) + supabaseResponse = NextResponse.next({ + request, }) - response.cookies.set({ name, value, ...options }) - }, - remove(name: string, options: any) { - request.cookies.set({ name, value: '', ...options }) - response = NextResponse.next({ - request: { headers: request.headers }, - }) - response.cookies.set({ name, value: '', ...options }) + cookiesToSet.forEach(({ name, value, options }) => + supabaseResponse.cookies.set(name, value, options) + ) }, }, } ) - // Check if user is authenticated - const { data: { user } } = await supabase.auth.getUser() + // IMPORTANT: Avoid writing any logic between createServerClient and + // supabase.auth.getUser(). A simple mistake could make it very hard to debug + // session issues. + const { + data: { user }, + } = await supabase.auth.getUser() // Protect all routes except /login if (!user && request.nextUrl.pathname !== '/login') { - return NextResponse.redirect(new URL('/login', request.url)) + // no user, potentially respond by redirecting the user to the login page + const url = request.nextUrl.clone() + url.pathname = '/login' + return NextResponse.redirect(url) } // If user is authenticated and tries to access login, redirect to home if (user && request.nextUrl.pathname === '/login') { - return NextResponse.redirect(new URL('/', request.url)) + const url = request.nextUrl.clone() + url.pathname = '/' + return NextResponse.redirect(url) } - return response + // IMPORTANT: You *must* return the supabaseResponse object as it is. If you're + // creating a new response object with NextResponse.next() make sure to: + // 1. Pass the request in it, like so: + // const myNewResponse = NextResponse.next({ request }) + // 2. Copy the cookies from the supabaseResponse to your new response + // myNewResponse.cookies.setAll(supabaseResponse.cookies.getAll()) + // 3. Change the myNewResponse object to fit your needs, but avoid changing + // the cookies! + // 4. Finally: + // return myNewResponse + // If this is not done, you may be causing the browser and server to go out + // of sync and terminate the user's session prematurely! + + return supabaseResponse } export const config = {