NextAuth 5中Google Provider自定义会话不生效,如何配置?
解决NextAuth 5中Google Provider自定义会话不生效的问题
问题根源
你当前的代码中,Google登录时jwt回调里的user参数是OAuth提供商返回的用户对象,仅包含name、email、image等基础字段,并不包含你数据库中存储的id、nama、alamat等自定义字段。因此直接赋值token.id = user.id会得到undefined,最终导致session回调无法注入自定义用户信息。同时,signIn回调中虽然创建/查询了数据库用户,但没有将数据库用户的信息传递给后续的jwt回调,导致后续流程拿不到数据库中的用户数据。
解决方案
方案一:在signIn回调中传递数据库用户信息
修改signIn回调,将查询/创建后的数据库用户信息赋值给user对象,让后续jwt回调能直接获取到完整的数据库用户数据:
callbacks: { async signIn({ user, account }) { if (account?.provider === "google") { let dbUser = await prisma.users.findUnique({ where: { email: user.email as string }, }); if (!dbUser) { // 创建新用户后,把返回的数据库用户对象赋值给dbUser dbUser = await prisma.users.create({ data: { email: user.email as string, nama: user.name as string, provider: "google", provider_id: account.providerAccountId as string, image: user.image as string, status: true, }, }); } // 将数据库用户的字段赋值给user对象,传递给后续回调 user.id = dbUser.id; user.nama = dbUser.nama; user.alamat = dbUser.alamat; user.status = dbUser.status; user.createdAt = dbUser.createdAt; user.updatedAt = dbUser.updatedAt; user.tes = dbUser.tes; // 如果数据库存在该字段 } return true; }, async jwt({ token, user, account }) { if (account) { // 此时user已经是数据库用户对象,能正确获取所有字段 token.id = user.id as string; token.email = user.email as string; token.nama = user.nama; token.alamat = user.alamat; token.status = user.status; token.createdAt = user.createdAt; token.updatedAt = user.updatedAt; token.tes = user.tes; } return token; }, async session({ session, token }) { if (token) { session.user.id = token.id; session.user.email = token.email; session.user.nama = token.nama; session.user.alamat = token.alamat; session.user.status = token.status; session.user.createdAt = token.createdAt; session.user.updatedAt = token.updatedAt; session.user.tes = token.tes; } return session; }, }, });
方案二:在jwt回调中主动查询数据库用户
如果不想修改signIn回调,可以直接在jwt回调中根据用户邮箱查询数据库,确保获取到完整的用户信息:
callbacks: { async signIn({ user, account }) { if (account?.provider === "google") { let dbUser = await prisma.users.findUnique({ where: { email: user.email as string }, }); if (!dbUser) { await prisma.users.create({ data: { email: user.email as string, nama: user.name as string, provider: "google", provider_id: account.providerAccountId as string, image: user.image as string, status: true, }, }); } } return true; }, async jwt({ token, account }) { // 首次登录(account存在)或token中没有用户ID时,查询数据库 if (account || !token.id) { const dbUser = await prisma.users.findUnique({ where: { email: token.email as string }, }); if (dbUser) { token.id = dbUser.id; token.email = dbUser.email; token.nama = dbUser.nama; token.alamat = dbUser.alamat; token.status = dbUser.status; token.createdAt = dbUser.createdAt; token.updatedAt = dbUser.updatedAt; token.tes = dbUser.tes; } } return token; }, async session({ session, token }) { if (token) { session.user.id = token.id; session.user.email = token.email; session.user.nama = token.nama; session.user.alamat = token.alamat; session.user.status = token.status; session.user.createdAt = token.createdAt; session.user.updatedAt = token.updatedAt; session.user.tes = token.tes; } return session; }, }, });
说明
方案二更可靠,因为即使在token刷新时,也会主动从数据库拉取最新的用户信息,避免数据不一致的问题。
内容的提问来源于stack exchange,提问作者Sipintar BNI
相关产品推荐
相关产品推荐

