NextJS集成Supabase Auth后redirect导航不生效问题
NextJS + Supabase Auth 登录后无法跳转指定路由
问题现象
集成Supabase Auth到NextJS项目中,按照官方文档实现登录逻辑后,登录操作能成功创建用户会话,但页面始终停留在登录页,仅收到303响应,无法跳转到指定的/trips路由。
相关代码
app/(auth)/_actions/login.ts
"use server"; import { createClient } from "@/app/_utils/supabase/server"; import { revalidatePath } from "next/cache"; import { redirect } from "next/navigation"; export async function login(formData: FormData) { const supabase = createClient(); const data = { email: formData.get("email") as string, password: formData.get("password") as string, }; const request = await supabase.auth.signInWithPassword(data); if (request.error) { redirect("/404"); } console.log("Login successful, redirecting to /trips"); revalidatePath("/", "layout"); redirect("/trips"); }
app/(auth)/login/page.tsx
export default function Login() { return ( <main className="h-full w-full flex flex-col justify-between items-center pt-56 pb-24"> <form className="flex flex-col w-80" action={login}> <Input name="email" className="mb-5" fullWidth placeholder="Email" type="text" /> <div className="w-full mb-5"> <Input name="password" className="mb-1" fullWidth placeholder="Password" type="password" /> </div> <Button type="submit" uppercase={true} filled={true}> Inicia sesión </Button> </form> </main> ); }
app/_utils/supabase/server.ts
import { createServerClient, type CookieOptions } from "@supabase/ssr"; import { cookies } from "next/headers"; export function createClient() { const cookieStore = cookies(); return createServerClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { cookies: { getAll() { return cookieStore.getAll(); }, setAll(cookiesToSet) { try { cookiesToSet.forEach(({ name, value, options }) => cookieStore.set(name, value, options) ); } catch { } }, }, } ); }
问题分析与修复
1. 修复Cookie设置的静默错误
当前server.ts中的setAll方法包含空catch块,会导致Supabase设置会话cookie失败时无任何提示,进而让后续的跳转逻辑因为会话状态未正确持久化而失效。
修改app/_utils/supabase/server.ts,移除空catch块:
import { createServerClient, type CookieOptions } from "@supabase/ssr"; import { cookies } from "next/headers"; export function createClient() { const cookieStore = cookies(); return createServerClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { cookies: { getAll() { return cookieStore.getAll(); }, setAll(cookiesToSet) { cookiesToSet.forEach(({ name, value, options }) => cookieStore.set(name, value, options) ); }, }, } ); }
2. 简化Server Action逻辑
revalidatePath("/", "layout")在登录场景中并非必需,且redirect会立即终止函数执行,该语句实际不会生效。同时,错误处理可调整为更友好的方式,避免直接跳转到404页面。
修改app/(auth)/_actions/login.ts:
"use server"; import { createClient } from "@/app/_utils/supabase/server"; import { redirect } from "next/navigation"; export async function login(formData: FormData) { const supabase = createClient(); const data = { email: formData.get("email") as string, password: formData.get("password") as string, }; const { error } = await supabase.auth.signInWithPassword(data); if (error) { redirect("/login?error=invalid_credentials"); } redirect("/trips"); }
3. 额外检查项
- 确认
/trips路由已正确创建,且路由组件中没有未正确处理的权限拦截逻辑(比如未正确获取会话状态导致重定向回登录页)。 - 打开浏览器开发者工具的Network标签,检查303响应的目标地址是否为
/trips,同时查看Cookies面板确认Supabase的会话cookie已成功设置。
内容的提问来源于stack exchange,提问作者Diego Rios
相关产品推荐
相关产品推荐

