Prisma搭配Next-Auth对接Keycloak时因not-before-policy字段创建用户失败
解决办法
你遇到的报错本质是因为Prisma的@map配置仅用于映射数据库表的列名,不会处理Prisma客户端调用时传入的字段名,所以Keycloak返回的带短横线的字段名还是会触发Prisma的入参校验报错,以下是两个可直接落地的解决方案:
方案1:在next-auth的signIn回调中预处理字段(推荐)
这个方案无需修改Prisma相关配置,直接在next-auth调用适配器写入数据库前转换字段名即可:
- 打开你的next-auth配置文件(通常为
app/api/auth/[...nextauth]/route.ts或pages/api/auth/[...nextauth].ts) - 在
callbacks配置项中新增signIn回调,完成字段名转换,示例代码如下:
import NextAuth, { type NextAuthOptions } from "next-auth"; import KeycloakProvider from "next-auth/providers/keycloak"; import PrismaAdapter from "@next-auth/prisma-adapter"; import { prisma } from "@/lib/prisma"; export const authOptions: NextAuthOptions = { adapter: PrismaAdapter(prisma), providers: [ KeycloakProvider({ clientId: process.env.KEYCLOAK_CLIENT_ID!, clientSecret: process.env.KEYCLOAK_CLIENT_SECRET!, issuer: process.env.KEYCLOAK_ISSUER!, }), ], callbacks: { async signIn({ account }) { if (account) { // 将短横线命名的字段转换为Prisma模型中定义的下划线命名字段 account.not_before_policy = account["not-before-policy"]; // 删除原带短横线的字段,避免触发Prisma入参校验报错 delete account["not-before-policy"]; } return true; }, }, };
方案2:新增Prisma中间件统一处理字段转换
如果你不想修改next-auth的回调逻辑,也可以通过Prisma中间件在执行写入操作前自动转换字段名:
- 打开你初始化Prisma客户端的文件(通常为
lib/prisma.ts) - 新增全局中间件处理Account模型的创建逻辑,示例代码如下:
import { PrismaClient } from "@prisma/client"; const prisma = new PrismaClient(); // 新增中间件处理特殊字段名转换 prisma.$use(async (params, next) => { if (params.model === "Account" && params.action === "create") { const data = params.args.data; if ("not-before-policy" in data) { data.not_before_policy = data["not-before-policy"]; delete data["not-before-policy"]; params.args.data = data; } } return next(params); }); export default prisma;
注意事项
修改完Prisma的schema文件后一定要执行prisma generate命令重新生成Prisma客户端,否则@map的配置不会生效。如果后续Keycloak返回其他带特殊字符的字段,按照相同逻辑做字段名转换即可。
内容的提问来源于stack exchange,提问作者V. Homi
相关产品推荐
相关产品推荐

