You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 23:22:22