如何通过Next-Auth的Google Provider正确填充User表emailVerified字段
我最近在用create-t3-app搭建NextJS项目,它能自动配置TypeScript、tRPC、Prisma、NextAuth等工具的样板代码,但遇到了一个认证问题:使用NextAuth的Google Provider登录时,无法将用户的邮箱验证状态(Google返回的email_verified)正确同步到Prisma数据库。
Prisma Schema配置
我的schema.prisma中User模型定义如下:
model User { id String @id @default(cuid()) email String @unique emailVerified Boolean @default(false) password String? role Role @default(USER) name String? image String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime? accounts Account[] sessions Session[] }
NextAuth Google Provider配置
在[...nextauth].ts中的Google Provider配置:
GoogleProvider({ clientId: env.GOOGLE_CLIENT_ID, clientSecret: env.GOOGLE_CLIENT_SECRET, async profile(profile) { return { id: profile.sub, // 不提供会触发TypeScript错误 email: profile.email, emailVerified: profile.email_verified ? true : false, // 尝试将null/undefined转为布尔值 name: profile.name, image: profile.picture } } })
错误信息
虽然打印profile时email_verified为true,但创建用户时仍报错:
Invalid `p.user.create()` invocation in project/node_modules/@next-auth/prisma-adapter/dist/index.js:6:38 3 exports.PrismaAdapter = void 0; 4 function PrismaAdapter(p) { 5 return { → 6 createUser: (data) => p.user.create({ data: { email: 'dillanjwilding@gmail.com', emailVerified: null, ~~~~ name: 'Dillan Wilding', image: 'https://lh3.googleusercontent.com/a/AEdFTp6-ViCSaOvUJMTH3hVpajCfagYI73vx1uPVDYbuTw=s96-c' } }) Argument emailVerified for data.emailVerified must not be null. Please use undefined instead.
已尝试的方法
- 将Prisma模型中的
emailVerified改为email_verified,但Google Provider的默认profile函数不会传递该字段,无效。 - 暂时将
emailVerified设为可空(Boolean?)或移除,用户创建和认证能正常工作,但无法跟踪邮箱验证状态。
依赖版本
当前使用的依赖版本:
"dependencies": { "@next-auth/prisma-adapter": "~1.0.5", "@prisma/client": "~4.9.0", "@tanstack/react-query": "~4.20.4", "@trpc/client": "~10.6.0", "@trpc/next": "~10.6.0", "@trpc/react-query": "~10.6.0", "@trpc/server": "~10.6.0", "next": "~13.1.2", "next-auth": "~4.19.0", "react": "~18.2.0", "react-dom": "~18.2.0", "react-icons": "~4.7.1", "react-markdown": "~8.0.4", "react-syntax-highlighter": "~15.5.0", "remark-gfm": "~3.0.1", "superjson": "~1.12.2", "zod": "~3.20.2" },
更新:我查阅了NextAuth源码,发现部分场景使用布尔类型的email_verified,部分使用日期类型的emailVerified,正在梳理流程和钩子调用顺序,寻求解决方案。
解决办法
问题根源是NextAuth的Prisma Adapter默认遵循官方User模型定义,其中emailVerified为日期类型(记录验证完成时间),而你定义的是布尔类型。Adapter会忽略非预期类型的字段,导致传递给Prisma的emailVerified为null,触发报错。
方式1:适配NextAuth默认的日期类型
修改Prisma模型,将emailVerified改为可空日期类型:
model User { // ... 其他字段不变 emailVerified DateTime? // 改为可空日期类型 // ... 其他字段不变 }
然后在Google Provider的profile函数中,将email_verified转为日期值:
async profile(profile) { return { id: profile.sub, email: profile.email, emailVerified: profile.email_verified ? new Date() : null, name: profile.name, image: profile.picture } }
方式2:自定义Prisma Adapter的createUser方法
若坚持使用布尔类型,可自定义Adapter的createUser方法,手动处理字段:
import { PrismaAdapter } from "@next-auth/prisma-adapter"; import { PrismaClient } from "@prisma/client"; const prisma = new PrismaClient(); const adapter = { ...PrismaAdapter(prisma), createUser: async (data) => { return prisma.user.create({ data: { ...data, emailVerified: data.emailVerified ?? false, // 确保传递布尔值,而非null }, }); }, }; // 在NextAuth配置中使用自定义adapter export default NextAuth({ adapter, providers: [/* 你的Provider配置 */], // ...其他配置 });
同时,需在types/next-auth.d.ts中扩展类型,确保NextAuth的User类型与Prisma模型匹配:
import NextAuth from "next-auth"; import { User as PrismaUser } from "@prisma/client"; declare module "next-auth" { interface User extends PrismaUser {} }
内容的提问来源于stack exchange,提问作者Dillan Wilding

