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

Next.js + Next-auth v5登录成功后重定向失败问题求助

问题分析与解决方案

在tRPC端点中直接调用signIn并依赖redirectTo参数实现重定向的方式不可行,原因是:tRPC mutation属于API请求,服务端抛出的NEXT_REDIRECT错误会被封装为API响应返回给前端,浏览器不会自动执行服务端的重定向指令——这种重定向逻辑仅在页面组件(如RSC或客户端页面)中抛出时才会生效。

以下是具体的修复方案:

1. 修改tRPC登录端点逻辑

将signIn的redirect参数设置为false,让它返回登录结果而非抛出重定向错误,再由前端手动处理跳转:

loginProcedure: publicProcedure.input(LoginSchema).mutation(async (opts) => {
  const { input } = opts;
  const validatedFields = LoginSchema.safeParse(input);
  if (!validatedFields.success) {
    throw new TRPCError({ code: "PARSE_ERROR", message: "Invalid fields" });
  }
  const { email, password } = validatedFields.data;

  // 关键:禁用自动重定向,获取登录结果对象
  const signInResult = await signIn("credentials", {
    email,
    password,
    redirectTo: DEFAULT_LOGIN_REDIRECT,
    redirect: false,
  });

  // 处理登录错误
  if (signInResult?.error) {
    if (signInResult.error === "CredentialsSignin") {
      throw new TRPCError({
        code: "UNAUTHORIZED",
        message: "Invalid credentials",
      });
    }
    throw new TRPCError({
      code: "UNAUTHORIZED",
      message: "Something went wrong",
    });
  }

  // 返回成功信息与跳转目标,交给前端处理
  return { success: true, redirectTo: DEFAULT_LOGIN_REDIRECT };
}),

2. 前端手动处理重定向

在调用tRPC登录接口的组件中,通过useMutation的onSuccess钩子执行跳转:

import { useRouter } from "next/navigation";
import { trpc } from "@/trpc/client";

export default function LoginForm() {
  const router = useRouter();
  const { mutate, isLoading } = trpc.auth.login.useMutation({
    onSuccess: (data) => {
      // 使用Next.js路由跳转(推荐)
      router.push(data.redirectTo);
      // 或用原生方式:window.location.href = data.redirectTo;
    },
    onError: (error) => {
      // 展示错误提示,比如toast
      console.error(error.message);
    },
  });

  // 表单提交逻辑
  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    const formData = new FormData(e.target as HTMLFormElement);
    mutate({
      email: formData.get("email") as string,
      password: formData.get("password") as string,
    });
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* 表单内容 */}
      <button type="submit" disabled={isLoading}>登录</button>
    </form>
  );
}

3. 验证Middleware配置

确保DEFAULT_LOGIN_REDIRECT对应的路径不会被Middleware拦截:

  • 该路径不应出现在authRoutes数组中(否则已登录用户访问会被循环重定向)
  • 如果路径不属于publicRoutes,Middleware中!isLoggedIn && !isPublicRoute的逻辑会拦截未登录用户,这符合预期,但已登录用户可以正常访问

内容的提问来源于stack exchange,提问作者Carlos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 21:53:10