Next.js NextAuth多用户类型会话ID与名称返回异常问题
NextAuth多用户类型会话问题修复方案
问题根源分析
1. 孩子登录返回家长ID
现有session回调中,会同时查询User(家长)和Kids(孩子)表,且优先匹配家长用户。如果孩子的用户名恰好和某个家长的用户名重复,就会错误返回家长ID;另外,孩子登录的分支没有限定只查孩子表,导致跨表匹配错误。
2. 孩子会话无用户名
session回调仅给session.user赋值了id,未同步孩子的用户名字段,前端自然拿不到名称信息。
修复代码
1. 修正Session回调
修改逻辑,区分家长/孩子的查询路径,同步完整用户信息:
async session({ session, user }) { console.log("sessions start", user); try { await connectToDB(); let currentUser = null; // 家长用户:通过email匹配User表 if (session.user?.email) { currentUser = await User.findOne({ email: session.user.email }); if (currentUser) { session.user.id = currentUser._id.toString(); session.user.name = currentUser.username; session.user.type = "parent"; // 标记用户类型,方便前端判断 } } // 孩子用户:仅通过username匹配Kids表,避免跨表冲突 else if (session.user?.name) { currentUser = await Kids.findOne({ username: session.user.name }); if (currentUser) { session.user.id = currentUser._id.toString(); session.user.name = currentUser.username; session.user.type = "kid"; // 标记用户类型 } } return session; } catch (error) { console.error("Error retrieving session:", error); throw error; } },
2. 补充Credentials登录的Authorize函数
孩子通过Credentials登录时,确保返回正确的用户标识信息(不要返回email,避免触发家长分支):
async authorize(credentials) { await connectToDB(); // 验证孩子账号(假设传入username和password) const kid = await Kids.findOne({ username: credentials.username }); if (!kid) return null; // 密码验证(示例用bcrypt,根据你的加密方式调整) const isValid = await bcrypt.compare(credentials.password, kid.password); if (!isValid) return null; // 返回孩子信息,name字段对应Kids表的username return { id: kid._id.toString(), name: kid.username }; },
3. 优化Google登录的SignIn回调
修正无效的用户名替换逻辑:
async signIn({ profile }) { try { await connectToDB(); const userExist = await User.findOne({ email: profile?.email }); if (!userExist) { await User.create({ email: profile?.email, // 处理用户名:替换多空格为单个,转小写并去首尾空格 username: profile?.name?.replace(/\s+/g, " ").toLowerCase().trim(), image: profile?.picture, points: 0, completedTasks: [], ongoingTasks: [], kids: [], }); } return true; } catch (error) { console.error("Error signing in:", error); throw error; } },
额外注意事项
- 确保
Kids表的username字段设置唯一索引,避免重名导致匹配错误。 - 前端可通过
session.user.type字段区分用户类型,执行对应业务逻辑。
内容的提问来源于stack exchange,提问作者winos
相关产品推荐
相关产品推荐

