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

Next.js自定义后端认证时,如何获取API返回的错误信息?

解决方案:在Next-Auth中返回自定义登录错误并实现重定向

核心问题分析

Next-Auth默认会将authorize函数中抛出的错误包装为通用的CredentialsSignin类型,导致客户端无法直接获取API返回的自定义错误信息(如"邮箱未验证")。要解决这个问题,关键在于让客户端能识别具体错误类型,并基于此执行重定向或提示逻辑。


步骤1:优化authorize函数,抛出明确错误信息

直接将API返回的错误信息抛出,无需额外包装,确保错误内容能传递到客户端:

authorize: async (credentials) => {
    const payload = await LoginSchema.parseAsync(credentials);
    const response = await loginUser(payload);
    const { status, user, message } = response as LoginResultProps;

    if (status !== "success") {
        // 直接抛出API返回的原始错误信息
        throw new Error(message ?? "登录失败,请稍后重试");
    }

    return user || null;
},

步骤2:客户端调用signIn时禁用自动跳转,处理自定义错误

设置redirect: false阻止Next-Auth自动跳转,手动处理返回结果,根据错误信息执行重定向或提示:

try {
    // 关键:设置redirect: false,获取完整返回结果
    const res = await signIn("credentials", {
        ...payload,
        redirect: false,
    });

    if (!res?.error) {
        form.reset();
        toast({
            variant: "success",
            description: <ToastSuccess title="登录成功" />
        });

        const user_type = session?.data?.user.user_type as string;
        setTimeout(() => {
            if (user_type === "xx") router.push("/xx");
            if (user_type === "yy") router.push("/yy");
            if (user_type === "zz") router.push("/zz");
        }, 1500);
    } else {
        // 根据错误信息区分处理逻辑
        if (res.error.message === "Email not verified") {
            // 重定向到邮箱验证页面
            router.push("/verify-email");
        } else if (res.error.message === "Invalid login combination") {
            setNotificationType({
                type: "failed",
                title: "登录失败",
                description: "用户名或密码错误"
            });
            setIsOpenNotification(true);
        } else {
            setNotificationType({
                type: "failed",
                title: "登录失败",
                description: res.error.message
            });
            setIsOpenNotification(true);
        }
    }
} catch (error) {
    if (error instanceof AuthError) {
        setNotificationType({
            type: "failed",
            title: "登录失败",
            description: error.type === "CredentialsSignin" ? "无效登录凭证" : "登录出错"
        });
        setIsOpenNotification(true);
    } else {
        console.error(error);
        setNotificationType({
            type: "failed",
            title: "登录失败",
            description: "发生未知错误"
        });
        setIsOpenNotification(true);
    }
}

进阶:自定义错误类型(可选)

如果需要更严谨的错误区分,可以自定义错误类(注意:服务器端错误序列化后自定义属性可能丢失,建议优先用错误信息字符串判断):

// 自定义错误类
class AuthCustomError extends Error {
    type: "EmailNotVerified" | "InvalidCredentials" | "UnknownError";
    constructor(message: string, type: "EmailNotVerified" | "InvalidCredentials" | "UnknownError") {
        super(message);
        this.type = type;
    }
}

// 在authorize中抛出
if (message?.toLowerCase() === "email not verified") {
    throw new AuthCustomError("Email not verified", "EmailNotVerified");
} else if (message?.toLowerCase() === "invalid login combination") {
    throw new AuthCustomError("Invalid login combination", "InvalidCredentials");
} else {
    throw new AuthCustomError(message ?? "登录失败", "UnknownError");
}

客户端处理时,通过错误信息字符串匹配即可(序列化后自定义type属性可能无法传递)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 14:25:31