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

NextAuth:如何不重定向返回自定义错误

实现NextAuth用户名密码登录的自定义错误返回

1. 在authorize方法中抛出自定义错误

在[...nextauth].js/ts的CredentialsProvider配置里,直接抛出包含自定义信息的Error对象,替代默认的重定向或空返回:

import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials"

export default NextAuth({
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" }
      },
      async authorize(credentials) {
        // 模拟数据库查询逻辑
        const user = await fetchUserByEmail(credentials.email)
        
        if (!user) {
          throw new Error("无效的邮箱地址")
        }
        
        if (user.isBanned) {
          throw new Error("账户已封禁")
        }
        
        const isPasswordValid = await verifyPassword(credentials.password, user.passwordHash)
        if (!isPasswordValid) {
          throw new Error("无效密码")
        }
        
        return user
      }
    })
  ],
  session: { strategy: "jwt" },
  callbacks: {
    async jwt({ token, user }) {
      if (user) token.user = user
      return token
    },
    async session({ session, token }) {
      session.user = token.user
      return session
    }
  },
  pages: {
    signIn: "/login"
  },
  debug: process.env.NODE_ENV === "development"
})

2. 客户端调用signIn时捕获自定义错误

客户端调用signIn时,必须设置redirect: false,这样会返回包含错误信息的对象而非直接重定向,然后通过result.error获取自定义消息:

import { signIn } from "next-auth/react"

const handleLogin = async (email, password) => {
  try {
    const result = await signIn("credentials", {
      email,
      password,
      redirect: false // 关键:禁用重定向,获取返回结果
    })
    
    if (result.ok) {
      // 登录成功逻辑,比如跳转首页
      window.location.href = "/"
    } else {
      // 拿到自定义错误消息,展示给用户
      console.error("登录失败:", result.error)
      setError(result.error)
    }
  } catch (error) {
    // 处理网络等意外错误
    console.error("登录请求出错:", error)
    setError("登录请求失败,请稍后重试")
  }
}

3. 进阶:返回自定义错误码

如果需要返回结构化的错误码(如INVALID_EMAIL),可以给Error对象添加code属性,再通过自定义错误处理逻辑返回给客户端:

修改authorize方法

async authorize(credentials) {
  const user = await fetchUserByEmail(credentials.email)
  
  if (!user) {
    const error = new Error("无效的邮箱地址")
    error.code = "INVALID_EMAIL"
    throw error
  }
  
  if (user.isBanned) {
    const error = new Error("账户已封禁")
    error.code = "ACCOUNT_BANNED"
    throw error
  }
  
  const isPasswordValid = await verifyPassword(credentials.password, user.passwordHash)
  if (!isPasswordValid) {
    const error = new Error("无效密码")
    error.code = "INVALID_PASSWORD"
    throw error
  }
  
  return user
}

添加自定义错误处理

在[...nextauth].js/ts中添加error回调,将错误码和消息以JSON格式返回:

export default NextAuth({
  // ...其他配置
  async error({ error, req, res }) {
    if (error.code) {
      res.status(401).json({
        error: error.message,
        code: error.code
      })
      return
    }
    res.status(500).json({ error: "服务器内部错误" })
  }
})

客户端捕获错误码

const handleLogin = async (email, password) => {
  try {
    const result = await signIn("credentials", {
      email,
      password,
      redirect: false
    })
    
    if (result.ok) {
      window.location.href = "/"
    } else {
      // 同时拿到错误码和消息
      console.error("错误码:", result.code, "错误消息:", result.error)
      setError(result.error)
    }
  } catch (error) {
    console.error("登录请求出错:", error)
    setError("登录请求失败,请稍后重试")
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 04:15:17