Next.js 15中NextAuth谷歌登录结合Sanity的问题排查——回调异常与用户资料创建问题
Next.js 15中NextAuth谷歌登录结合Sanity的问题排查——回调异常与用户资料创建问题
兄弟,我看你这问题核心就是加了signIn回调后Google登录就炸了,去掉就正常,大概率是回调里的逻辑踩了几个隐形坑,我帮你一一捋清楚:
1. 最可能的元凶:Google Profile字段完全搞反了!
你在signIn回调里解构的profile.id、profile.login、profile.bio,这些字段Google OAuth根本不返回啊!
NextAuth的Google Provider返回的Profile结构里:
- 用户的唯一Google ID是
profile.sub,不是id - 根本没有
login这个字段(那是GitHub的专属字段!) bio对应的是profile.aboutMe,而且得额外申请权限才能拿到,默认是没有的
你拿不存在的字段去查Sanity、创建文档,肯定会报错,导致signIn回调直接失败,登录流程直接卡壳。
临时排查方案:先在回调里打日志看真实的Profile结构,确认字段:
async signIn({ user, profile }) { console.log("真实的Google Profile:", profile); console.log("NextAuth封装的User:", user); // 先注释其他代码,返回true看看能不能正常登录 return true; }
2. Sanity写入的两个隐形坑
(1)Write Client权限不足
你的writeClient有没有配置正确的Sanity写入Token?这个Token必须有创建author文档的权限,不然创建操作会直接抛错,导致回调失败。
(2)Schema字段约束
如果你的Sanity author Schema里,username、id是必填字段,而你传了undefined(比如用了不存在的login字段),Sanity会直接拒绝创建,回调自然就失败了。
3. 给你修正后的完整可用代码
我把所有坑都填上了,你直接替换试试:
import NextAuth from "next-auth"; import Google from "next-auth/providers/google"; import { client } from "./sanity/lib/client"; import { AUTHOR_BY_GOOGLE_ID } from "./sanity/lib/queries"; import { writeClient } from "./sanity/lib/write-client"; export const { handlers, auth, signIn, signOut } = NextAuth({ providers: [ Google({ // 如果需要获取用户的aboutMe(即你要的bio),必须加这个权限 scope authorization: { params: { scope: "openid email profile https://www.googleapis.com/auth/userinfo.profile" } } }) ], callbacks: { async signIn({ user, profile }) { // 拿到正确的Google用户唯一ID const googleId = profile.sub; if (!googleId) { console.error("无法获取Google用户唯一ID"); return false; } try { // 查询Sanity里是否已有该用户 const existingUser = await client .withConfig({ useCdn: false }) .fetch(AUTHOR_BY_GOOGLE_ID, { id: googleId }); // 不存在则创建新用户 if (!existingUser) { // 用Google真实返回的字段填充,避免undefined const newAuthor = { _type: "author", id: googleId, name: user.name || `${profile.givenName} ${profile.familyName}`, // 用用户的名作为默认用户名,防止空值 username: profile.givenName || user.name?.split(" ")[0] || "unknown-user", email: user.email, image: user.image || profile.picture, // Google的bio是aboutMe字段,没有则留空 bio: profile.aboutMe || "", }; await writeClient.create(newAuthor); console.log("新用户已成功写入Sanity:", newAuthor); } return true; } catch (error) { // 捕获错误才能精准定位问题 console.error("登录回调执行失败:", error); return false; } }, async jwt({ token, account, profile }) { if (account && profile) { const googleId = profile.sub; const user = await client .withConfig({ useCdn: false }) .fetch(AUTHOR_BY_GOOGLE_ID, { id: googleId }); token.id = user?._id; } return token; }, async session({ session, token }) { Object.assign(session, { id: token.id }); return session; }, } });
最后还要检查这两点
- 你的
AUTHOR_BY_GOOGLE_ID查询是不是正确的?比如查询条件是id == $id,要和你传入的googleId完全对应 - Sanity的
authorSchema里,id字段是不是设置为string类型,并且开启了唯一值约束?
备注:内容来源于stack exchange,提问作者M3nnoun
相关产品推荐
相关产品推荐

