Next Auth v5:如何传递自定义时区数据至JWT与Session回调
在NextAuth v5中登录时传递并存储用户时区到Session
方法一:通过Credentials提供者直接传递(适用于自定义登录逻辑)
如果你用的是Credentials登录提供者,可以直接在signIn调用中传递时区,然后在授权流程中存入JWT和Session:
自定义登录页面调用
signIn时传入时区
在客户端组件的登录逻辑里,获取当前用户时区并作为参数传入signIn:import { signIn } from '@/auth'; const handleLogin = async () => { const userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone; await signIn('credentials', { email: userEmail, password: userPassword, timezone: userTimezone, redirect: true, callbackUrl: '/' }); };在Credentials提供者的
authorize回调中接收时区
在NextAuth配置里,定义Credentials提供者时,确保credentials包含timezone字段,并在authorize中获取该值,随用户数据一起返回:import NextAuth from 'next-auth'; import Credentials from 'next-auth/providers/credentials'; export const { handlers, auth, signIn, signOut } = NextAuth({ providers: [ Credentials({ credentials: { email: { label: 'Email', type: 'email' }, password: { label: 'Password', type: 'password' }, timezone: { type: 'text' } // 声明时区字段 }, authorize: async (credentials) => { // 替换为你的用户验证逻辑 const user = await validateUser(credentials.email, credentials.password); if (!user) return null; // 返回包含时区的用户数据 return { id: user.id, email: user.email, name: user.name, timezone: credentials.timezone }; } }) ], callbacks: { // 将时区存入JWT async jwt({ token, user }) { if (user) { token.timezone = user.timezone; } return token; }, // 将时区同步到Session async session({ session, token }) { session.user.timezone = token.timezone; return session; } } });
方法二:登录后通过API更新(适用于OAuth或无法直接传递的场景)
如果使用OAuth提供者(如Google、GitHub),无法直接在signIn时传递自定义参数,可以登录后通过API将时区存入数据库,再同步到Session:
客户端登录成功后调用API保存时区
在登录后的客户端组件中,获取时区并调用自定义API路由:import { useSession } from '@/auth'; const PostLogin = () => { const { update } = useSession(); useEffect(() => { const saveTimezone = async () => { const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone; await fetch('/api/save-timezone', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ timezone }) }); // 更新Session以获取最新的时区数据 await update(); }; saveTimezone(); }, [update]); return <div>登录成功,正在同步时区...</div>; };编写API路由处理时区存储
创建app/api/save-timezone/route.js,验证用户身份后将时区存入数据库:import { auth } from '@/auth'; import prisma from '@/lib/prisma'; export async function POST(req) { const session = await auth(); if (!session?.user?.id) { return new Response('Unauthorized', { status: 401 }); } const { timezone } = await req.json(); await prisma.user.update({ where: { id: session.user.id }, data: { timezone } }); return new Response('OK', { status: 200 }); }在Session回调中从数据库获取时区
修改NextAuth配置的session回调,从数据库读取时区并同步到Session:callbacks: { async session({ session, token }) { if (token.sub) { const user = await prisma.user.findUnique({ where: { id: token.sub }, select: { timezone: true } }); if (user) { session.user.timezone = user.timezone; } } return session; } }
注意事项
- 确保使用NextAuth v5的正确API,v5的配置方式与v4略有不同(比如直接导出
handlers、auth等)。 - 时区可以通过
Intl.DateTimeFormat().resolvedOptions().timeZone获取标准的IANA时区字符串(如Asia/Shanghai)。
内容的提问来源于stack exchange,提问作者ggrant
相关产品推荐
相关产品推荐

