NextAuth.js v5使用JWT策略更新服务端会话时activeCompanyId被重置为null的问题排查
嘿,我看了你的代码和问题描述,你遇到的情况是调用unstable_update更新会话后,activeCompanyId明明已经被正确设置,但后续又变回null对吧?结合你的代码,我梳理了几个大概率的原因和解决方向:
JWT回调中数据库查询的覆盖问题
你的jwt回调里有个逻辑:只要存在user参数(一般是登录初始化场景),就会从数据库拉取用户信息,然后把token.activeCompanyId设为数据库里的user.activeCompanyId。这里的隐患在于:如果你调用unstable_update的时候,只是临时更新了会话里的activeCompanyId,还没把这个新值同步到数据库,那后续任何触发jwt回调的请求(比如token刷新、新的接口请求),都会再次从数据库取出旧的(甚至是null的)activeCompanyId覆盖掉token里的新值,最终导致session里的activeCompanyId变回null。
解决思路:- 如果你的业务是先更新会话再同步数据库,那可以给
token.activeCompanyId的赋值加个判断——只有当token里还没有这个值的时候,才从数据库取:if (token.activeCompanyId === undefined) { token.activeCompanyId = userFromDb?.activeCompanyId; } - 如果业务逻辑要求先更数据库再更会话,那一定要确保调用
unstable_update之前,已经把新的activeCompanyId写入数据库,这样后续从数据库拉取的就是正确值。
- 如果你的业务是先更新会话再同步数据库,那可以给
确认
unstable_update传递的参数是否正确
你在trigger === 'update'分支里直接用session.user.activeCompanyId给token赋值,那得先确认调用unstable_update时传的参数是不是对的。比如你调用的代码是不是类似这样:await unstable_update(session, { user: { ...session.user, activeCompanyId: 新的公司ID } })如果传的
activeCompanyId本身就是null,那token里的值自然会被设成null。加日志排查token的变化过程
你可以在jwt回调的各个分支都加上日志,追踪activeCompanyId的变化。比如在数据库查询后打印取出的值,在update分支打印传入的session值:if (user) { const userId = token.sub as string; const userFromDb = await prisma.user.findUnique({ where: { id: +userId }, }); console.log('从数据库拿到的activeCompanyId:', userFromDb?.activeCompanyId); // ...其他赋值逻辑 } if (trigger === 'update') { console.log('Update触发时传入的session.activeCompanyId:', session.user.activeCompanyId); token.activeCompanyId = session.user.activeCompanyId; }这样就能清楚看到是哪一步把
activeCompanyId改成null的。注意
unstable_update的特性限制
毕竟unstable_update是NextAuth v5的不稳定API,可能存在一些边缘情况。比如更新后,客户端的旧session可能还没失效,导致后续请求用的还是旧token。这种情况下,可以在更新会话后,强制触发一次session刷新(比如服务端调用getSession()重新获取,客户端调用useSession()的刷新方法),确保拿到的是最新的会话数据。
你可以先从第一个原因入手排查,这应该是最常见的触发场景。
备注:内容来源于stack exchange,提问作者justelio19

