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

Next Auth v5:如何正确实现授权失败逻辑?

问题分析与解决方案

1. 核心错误:违反Credentials Provider的返回值规范

NextAuth.js的Credentials Provider对authorize方法的返回值有严格限制:

  • 验证成功:必须返回包含用户标识的user对象(如{ id: 'xxx', email: 'xxx' })
  • 验证失败:必须返回null

你返回错误对象的行为不符合设计规范,NextAuth会将非null/非user对象的返回值误判为验证成功,进而触发后续的jwt、session回调并生成authjs.session-token Cookie,这就是异常行为的根源。

2. 优化验证失败的处理逻辑(返回null时的解决方案)

当authorize返回null时,NextAuth会抛出CredentialsSignin错误,这是预期行为,可通过以下方式优化日志和错误捕获:

(1)自定义错误信息,减少冗余日志

在auth.ts的Credentials Provider配置中,通过抛出特定错误替代默认的CredentialsSignin,同时自定义日志过滤规则:

// auth.ts
import Credentials from "next-auth/providers/credentials";
import { AuthOptions } from "next-auth";

export const authOptions: AuthOptions = {
  providers: [
    Credentials({
      name: "MagicLink",
      credentials: { token: { label: "Token", type: "text" } },
      async authorize(credentials) {
        if (!credentials?.token) {
          throw new Error("missing_token");
        }
        // 验证token逻辑
        const isValidToken = await verifyMagicToken(credentials.token);
        if (!isValidToken) {
          throw new Error("invalid_token");
        }
        // 验证成功返回用户对象
        return { id: "user_unique_id", email: "user@example.com" };
      },
    }),
  ],
  // 自定义日志过滤,忽略预期内的认证错误
  logger: {
    error(code, metadata) {
      if (code !== "CredentialsSignin") {
        console.error(`NextAuth Error [${code}]:`, metadata);
      }
    },
    warn(code) { console.warn(`NextAuth Warn [${code}]`); },
    debug(code, metadata) {
      if (process.env.NODE_ENV === "development") {
        console.debug(`NextAuth Debug [${code}]:`, metadata);
      }
    },
  },
};

(2)Server Action中正确捕获错误

调用signIn时设置redirect: false,禁止自动跳转,直接获取包含错误信息的结果对象,避免捕获NEXT_REDIRECT错误:

// app/auth/magiclogin/callback/actions.ts
"use server";

import { signIn } from "next-auth/react";
import { redirect } from "next/navigation";

export async function handleMagicLinkCallback(token: string | null) {
  try {
    const result = await signIn("credentials", {
      token: token,
      redirect: false, // 关键:禁用自动跳转,返回结果对象
    });

    if (result?.error) {
      // 获取自定义错误码,如"missing_token"或"invalid_token"
      return { error: result.error };
    }

    // 验证成功后跳转
    redirect("/");
  } catch (error) {
    // 仅捕获非认证类异常,如网络错误
    return { error: "unexpected_error" };
  }
}

(3)确保jwt/session回调仅在验证成功时触发

在回调逻辑中增加判断,只有存在用户信息时才执行后续操作:

// auth.ts 中添加到authOptions
callbacks: {
  async jwt({ token, user }) {
    // 仅当验证成功(user存在)时更新token
    if (user) token.id = user.id;
    return token;
  },
  async session({ session, token }) {
    // 仅当token包含用户ID时更新session
    if (token.id) session.user.id = token.id;
    return session;
  },
},

3. 关键注意事项

  • 永远不要在authorize中返回错误对象,否则会导致NextAuth误判验证状态
  • redirect: false是在Server Action中捕获清晰错误的核心配置
  • 自定义错误码后,可在前端将其映射为用户友好的提示文本

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 19:22:55