Next-Auth v5.0.0-beta.5凭证认证失败时返回自定义错误的方法
NextAuth v5 凭证认证失败返回自定义错误方案
在NextAuth v5中,authorize函数的错误处理机制相比v4有调整,直接抛出JSON字符串形式的Error仍然可行,但需要配合客户端的signIn调用方式来正确获取并解析自定义错误信息。以下是具体实现方案:
服务器端配置(Auth Route)
修改你的认证路由文件(通常是app/api/auth/[...nextauth]/route.ts),在credentials provider的authorize函数中,当认证失败时抛出包含自定义错误信息的JSON字符串:
import NextAuth from "next-auth"; import Credentials from "next-auth/providers/credentials"; // 导入你的API实例和类型定义 import AuthApiInstance from "@/services/auth-api"; import type { UserSchemaType } from "@/types/auth"; import { encryptCookieDataAction, EncryptionCookiesKeys } from "@/utils/cookies"; export const { handlers, auth, signIn, signOut } = NextAuth({ providers: [ Credentials({ credentials: { email: { label: "邮箱", type: "email" }, password: { label: "密码", type: "password" }, }, async authorize(credentials) { // 校验必填参数 if (!credentials?.email || !credentials?.password) { throw new Error(JSON.stringify({ errors: "缺少邮箱或密码", status: 400 })); } // 调用后端登录接口 const urlencoded = new URLSearchParams(); urlencoded.append('email', credentials.email); urlencoded.append('password', credentials.password); const res = await AuthApiInstance.signIn<UserSchemaType>(urlencoded); // 处理接口错误 if (res.isError && !res.resData) { throw new Error(JSON.stringify({ errors: res.error, status: res.statusCode })); } // 存储加密后的token if (res.resData?.data.token) { encryptCookieDataAction(res.resData.data.token, EncryptionCookiesKeys.AdminToken); } // 返回用户信息(认证成功) return res.resData?.data as any; }, }), ], // 可选:指定错误页面(当redirect为true时跳转) pages: { error: "/auth/error", }, });
客户端处理方式
方式1:不跳转,直接获取错误(推荐)
调用signIn时设置redirect: false,这样会返回包含错误信息的结果对象,你可以直接解析并展示自定义错误:
"use client"; import { signIn } from "next-auth/react"; import { useRouter } from "next/navigation"; import { useState } from "react"; export default function LoginForm() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [loginError, setLoginError] = useState<{errors?: string, status?: number} | null>(null); const router = useRouter(); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setLoginError(null); const result = await signIn("credentials", { email, password, redirect: false, // 禁止自动跳转 }); if (result?.error) { // 解析自定义错误信息 try { const customError = JSON.parse(result.error); setLoginError(customError); } catch { // 解析失败时设置默认错误 setLoginError({ errors: "登录失败", status: 500 }); } } else if (result?.ok) { // 登录成功,跳转到目标页面 router.push("/dashboard"); } }; return ( <form onSubmit={handleSubmit}> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="邮箱" required /> <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="密码" required /> <button type="submit">登录</button> {loginError && ( <div className="error"> <p>错误信息:{loginError.errors}</p> <p>状态码:{loginError.status}</p> </div> )} </form> ); }
方式2:跳转到错误页面展示
如果使用默认的redirect: true(或不设置),认证失败后会跳转到你配置的错误页面,你可以通过useSearchParams获取错误参数并解析:
"use client"; import { useSearchParams } from "next/navigation"; export default function AuthErrorPage() { const searchParams = useSearchParams(); const errorParam = searchParams.get("error"); let errorInfo = null; if (errorParam) { try { errorInfo = JSON.parse(errorParam); } catch { errorInfo = { errors: "未知错误", status: 500 }; } } return ( <div className="auth-error"> <h2>登录失败</h2> {errorInfo && ( <> <p>错误详情:{errorInfo.errors}</p> <p>状态码:{errorInfo.status}</p> </> )} <a href="/login">返回登录页</a> </div> ); }
关键说明
- v5中
authorize函数仍可通过抛出Error传递错误信息,但需确保错误内容是可解析的JSON字符串。 - 客户端必须通过
redirect: false获取返回结果,或在错误页面解析URL查询参数,才能拿到自定义错误结构。 - 若解析JSON失败,建议添加兜底逻辑,避免页面崩溃。
内容的提问来源于stack exchange,提问作者Hashira
相关产品推荐
相关产品推荐

