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

使用NextAuth.js CredentialsProvider时回调函数未触发问题

问题分析与解决方案

你的核心问题出在**authorize函数的异步处理逻辑错误**,导致NextAuth无法正确获取验证后的用户数据,直接判定登录失败,因此session和jwt回调根本不会触发。结合你的日志来看,POST /api/auth/callback/credentials返回302重定向到错误页,完全符合这个判断。

具体问题点

  • authorize函数未正确返回异步结果:你用了fetch().then()链式调用,但没有把整个Promise链作为async函数的返回值,导致函数会立即返回undefined,NextAuth直接判定验证失败。
  • 条件判断逻辑冗余错误:const cond = response?.jwt !== null; if(cond !== null)这部分逻辑完全多余,只要response.jwt存在就应该返回用户数据,额外判断反而可能引发逻辑混乱。
  • 错误处理静默吞错:catch块为空,没有正确抛出错误,导致NextAuth无法感知验证失败的具体原因,只能返回通用的CredentialsSignin错误。
  • session回调参数误用:当使用jwt会话策略时,session回调中的user参数是undefined,你应该从token中读取用户信息。

修复后的完整配置代码

import GoogleProvider from 'next-auth/providers/google';
import CredentialsProvider from 'next-auth/providers/credentials';
import base_url from '@/app/_util/StrapiConfig';

export const options = {
    providers: [
        CredentialsProvider({
            name: 'Credentials',
            credentials: {
                email: { label: "Email", type: "text", placeholder: "Please enter your email" },
                password: { label: "Password", type: "password" },
            },
            async authorize(credentials, req) {
                const { email, password } = credentials;
                try {
                    // 改用await处理异步请求,确保函数等待请求完成后再返回结果
                    const res = await fetch(base_url + `/auth/local`, {
                        headers: {
                            'Authorization': `Bearer ${process.env.NEXT_PUBLIC_STRAPI_TOKEN}`,
                            'Content-Type': 'application/json',
                        },
                        method: 'POST',
                        body: JSON.stringify({
                            identifier: email,
                            password: password,
                        })
                    });
                    
                    const response = await res.json();

                    // 直接检查jwt是否存在,判断验证是否成功
                    if (response.jwt) {
                        return response;
                    }

                    // 根据后端返回的错误信息抛出对应错误
                    if (response.error?.status === 403) {
                        throw new Error('User with this email is not registered!');
                    } else if (response.error?.status === 401) {
                        throw new Error('Invalid credentials!');
                    } else {
                        throw new Error('Something went wrong!');
                    }
                } catch (error) {
                    // 将错误抛出,让NextAuth处理并展示错误信息
                    throw new Error(error.message);
                }               
            }
        })
    ],
    session: {
        strategy: "jwt",
    },
    secret: process.env.AUTH_SECRET,
    debug: process.env.NODE_ENV === 'development',
    callbacks: {
        async session({session, token}) {
            console.log("session", session);
            // 从token中获取用户信息,而非user参数(jwt策略下user参数不存在)
            session.user.email = token.user.email;
            session.jwt = token.jwt;
            return session;
        },
        async jwt({token, user}) {
            console.log("token", token);
            if(user) {
                token.user = user.user; // Strapi返回的用户数据在response.user字段中
                token.jwt = user.jwt;
            }
            return token;
        },
    }
}

关键修改说明

  1. 异步请求改用await:确保authorize函数等待后端响应完成后再返回结果,避免函数提前返回undefined。
  2. 简化条件判断逻辑:直接检查response.jwt是否存在,去掉冗余的中间变量判断。
  3. 正确抛出错误:在catch块中重新抛出错误,让NextAuth能够捕获并展示对应的错误信息,而非静默失败。
  4. 调整回调参数使用:
    • jwt回调中,适配Strapi的返回结构,将token.user设为user.user。
    • session回调中,从token中读取用户信息,因为jwt策略下不会传入user参数。

验证修复效果

修改后重新测试登录,你会发现:

  • POST /api/auth/callback/credentials会返回正常状态码或正确重定向,不再跳转到错误页。
  • jwt和session回调中的console.log会正常输出内容。
  • 用户登录状态会被正确维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 13:13:20