使用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; }, } }
关键修改说明
- 异步请求改用
await:确保authorize函数等待后端响应完成后再返回结果,避免函数提前返回undefined。 - 简化条件判断逻辑:直接检查
response.jwt是否存在,去掉冗余的中间变量判断。 - 正确抛出错误:在
catch块中重新抛出错误,让NextAuth能够捕获并展示对应的错误信息,而非静默失败。 - 调整回调参数使用:
jwt回调中,适配Strapi的返回结构,将token.user设为user.user。session回调中,从token中读取用户信息,因为jwt策略下不会传入user参数。
验证修复效果
修改后重新测试登录,你会发现:
POST /api/auth/callback/credentials会返回正常状态码或正确重定向,不再跳转到错误页。jwt和session回调中的console.log会正常输出内容。- 用户登录状态会被正确维护。
内容的提问来源于stack exchange,提问作者SMEET KOTHARI
相关产品推荐
相关产品推荐

