NextAuth v4 Beta数据库会话:存储OneLogin OAuth登录返回的额外字段方法
解决方案
步骤1:自定义OneLogin Provider的profile回调
该回调负责将OneLogin返回的OAuthProfile字段转换为NextAuth可识别的用户结构,你可以直接在这一步完成字段映射和自定义字段初始化:
// 你的NextAuth配置文件,比如app/api/auth/[...nextauth]/route.ts import NextAuth from "next-auth" import OneLoginProvider from "next-auth/providers/onelogin" import { MongoDBAdapter } from "@next-auth/mongodb-adapter" import clientPromise from "@/lib/mongodb" // 替换为你自己的MongoDB连接实例导出路径 export const { handlers, auth, signIn, signOut } = NextAuth({ adapter: MongoDBAdapter(clientPromise), providers: [ OneLoginProvider({ clientId: process.env.ONELOGIN_CLIENT_ID, clientSecret: process.env.ONELOGIN_CLIENT_SECRET, issuer: process.env.ONELOGIN_ISSUER, // 新增profile回调处理字段映射 profile(profile) { return { id: profile.sub, // 必填,NextAuth要求的用户唯一标识 name: profile.given_name, // 直接将given_name赋值给name字段 email: profile.email, // 保留必填的邮箱字段 family_name: profile.family_name, // 新增需要存储的额外字段 preferred_username: profile.preferred_username, // 新增需要存储的额外字段 auth_level: "user" // 新增默认权限字段 } } }) ], })
步骤2:扩展MongoDB适配器支持存储自定义字段
默认MongoDB适配器只会写入NextAuth预设的标准字段(id/name/email/emailVerified/image),你需要重写createUser方法将自定义字段存入users集合:
// 在NextAuth配置文件中调整适配器配置 const baseAdapter = MongoDBAdapter(clientPromise) const customAdapter = { ...baseAdapter, async createUser(user) { // 将所有自定义字段传入创建用户的逻辑 return baseAdapter.createUser({ ...user, family_name: user.family_name, preferred_username: user.preferred_username, auth_level: user.auth_level }) } } // 替换原有adapter配置为自定义适配器 export const { handlers, auth, signIn, signOut } = NextAuth({ adapter: customAdapter, // 剩余配置保持不变 providers: [/* ... */] })
步骤3:(可选)同步自定义字段到会话
如果需要在前端通过useSession()或服务端auth()方法拿到这些自定义字段,需要额外配置回调:
如果你使用JWT会话
export const { handlers, auth, signIn, signOut } = NextAuth({ // 其他配置不变 session: { strategy: "jwt" }, callbacks: { async jwt({ token, user }) { // 首次登录时将用户字段存入token if (user) { token.family_name = user.family_name token.preferred_username = user.preferred_username token.auth_level = user.auth_level } return token }, async session({ session, token }) { // 将token中的字段同步到session if (session.user) { session.user.family_name = token.family_name as string session.user.preferred_username = token.preferred_username as string session.user.auth_level = token.auth_level as string } return session } } })
如果你使用数据库会话
export const { handlers, auth, signIn, signOut } = NextAuth({ // 其他配置不变 session: { strategy: "database" }, callbacks: { async session({ session, user }) { // 直接从数据库查询到的user对象中取字段同步到session if (session.user) { session.user.family_name = user.family_name session.user.preferred_username = user.preferred_username session.user.auth_level = user.auth_level } return session } } })
步骤4:(可选)TypeScript类型扩展
如果你的项目使用TypeScript,需要新增类型声明文件扩展NextAuth的内置类型,避免类型报错:
// types/next-auth.d.ts import NextAuth from "next-auth" declare module "next-auth" { interface User { family_name: string preferred_username: string auth_level: string } interface Session { user: User } } // 如果使用JWT会话还需要扩展JWT类型 declare module "next-auth/jwt" { interface JWT { family_name: string preferred_username: string auth_level: string } }
内容的提问来源于stack exchange,提问作者Vpp Man
相关产品推荐
相关产品推荐

