Next-Auth第三方登录时如何将自定义角色与ID存入Session?
解决NextAuth第三方登录(Google)自定义字段存入Session的问题
你的问题核心在于第三方登录时,jwt回调无法获取到数据库中用户的_id、admin、banned字段——默认第三方登录返回的user对象只包含基础信息(如name、email),没有你自定义的字段。以下是具体修复步骤:
1. 修改signIn回调:传递数据库完整用户信息
在signIn回调中,无论用户是首次注册还是已存在,都要从数据库取出完整的用户文档,并将自定义字段附加到user对象中,确保后续jwt回调能拿到这些数据:
async signIn({ user }) { await db.connect(); let dbUser = await Users.findOne({ email: user?.email }); // 首次登录:创建用户并获取新文档 if (!dbUser) { try { const userSchema = { name: user?.name || '', email: user?.email || '', password: 'Signed using google', picture: profilePictures[Math.floor(Math.random()*profilePictures.length)].path || '/images/TpAnime.jpg', bookMark: { animeList: [], watchList: [] }, banned: false, admin: false, }; dbUser = await Users.create(userSchema); } catch (err) { throw new Error("Something Went Wrong!, Try Signing With Another Account."); } } // 将数据库用户的自定义字段附加到user对象 user._id = dbUser._id; user.admin = dbUser.admin; user.banned = dbUser.banned; await db.disconnect(); return true; // 允许登录 }
2. 优化jwt回调:确保字段正确存入Token
修改后的jwt回调会在首次登录时,从已注入自定义字段的user对象中提取信息存入Token,后续Token刷新时也能保留这些字段:
async jwt({ token, user }) { // 首次登录(user存在时),存入自定义字段 if (user) { token._id = user._id; token.admin = user.admin; token.banned = user.banned; } // 可选:后续Token刷新时,同步数据库最新的权限状态 // if (token.email) { // const dbUser = await Users.findOne({ email: token.email }); // token.admin = dbUser.admin; // token.banned = dbUser.banned; // } return token; }
3. 保持session回调不变
你的session回调已经正确将Token中的字段映射到Session,无需修改:
async session({ session, token }) { if (token?._id) session.user._id = token._id; if (typeof token?.admin === "boolean") session.user.admin = token.admin; if (typeof token?.banned === "boolean") session.user.banned = token.banned; return session; }
关键原理说明
- 第三方登录时,
signIn回调是唯一能将用户身份与数据库关联的环节,必须在这里把自定义字段注入到user对象中。 jwt回调在首次登录时会收到user参数,此时将自定义字段存入Token,后续每次请求都会从Token中读取这些字段,最终通过session回调传递给前端。
内容的提问来源于stack exchange,提问作者Viper
相关产品推荐
相关产品推荐

