NextJS 14 + Auth.js v5:凭证登录后Session需手动刷新显示
NextJS 14 + Auth.js v5 凭证登录后Session不自动更新问题
问题现象
- OAuth(如Github)登录后跳转至设置页,Session自动更新,页面正常展示对应设置选项
- 凭证(Credentials)登录后跳转至设置页,Session无法自动更新,必须手动刷新页面才能看到完整会话数据
问题原因
Auth.js v5的OAuth登录流程会自动触发客户端Session同步,但凭证登录的signIn方法默认不会主动更新客户端Session状态。同时Root Layout中通过auth()获取的初始Session是服务器端渲染结果,客户端跳转后不会自动重新获取最新Session。
修复方案
1. 凭证登录后手动触发Session更新
在凭证登录的处理逻辑中,登录成功后调用useSession的update方法,确保客户端Session同步:
// 登录组件内的凭证登录处理逻辑 const handleLogin = async () => { const result = await signIn("credentials", { email: formValues.email, password: formValues.password, redirect: false, // 关闭自动跳转,手动控制流程 }); if (result?.ok) { const { update } = useSession(); update(); // 手动更新客户端Session router.push("/settings"); // 跳转至设置页 } };
2. 优化用户信息获取钩子
修改useCurrentUser钩子,确保Session加载完成后再返回用户数据:
"use client"; import { useSession } from "next-auth/react"; export const useCurrentUser = () => { // 强制等待Session加载完成 const session = useSession({ required: true }); return session.data?.user; };
3. 完善Auth.js的凭证提供者配置
确保凭证登录的authorize方法返回完整用户信息,同时通过JWT回调将用户字段同步到Session中:
// auth.ts 中的配置片段 export const { auth, handlers, signIn, signOut } = NextAuth({ providers: [ Credentials({ credentials: { email: { label: "邮箱", type: "email" }, password: { label: "密码", type: "password" }, }, async authorize(credentials) { // 验证用户逻辑(示例) const user = await getUserByEmail(credentials?.email as string); if (!user || !user.password) return null; const passwordMatch = await bcrypt.compare( credentials?.password as string, user.password ); if (passwordMatch) { // 返回包含所有必要字段的用户对象 return { id: user.id, name: user.name, email: user.email, role: user.role, isOAuth: user.isOAuth, }; } return null; }, }), // 其他OAuth提供者配置... ], session: { strategy: "jwt" }, callbacks: { async jwt({ token, user }) { // 登录时将用户信息合并到JWT token if (user) { token.id = user.id; token.role = user.role; token.isOAuth = user.isOAuth; } return token; }, async session({ session, token }) { // 将JWT中的字段同步到Session用户对象 if (session.user) { session.user.id = token.id as string; session.user.role = token.role as string; session.user.isOAuth = token.isOAuth as boolean; } return session; }, }, });
4. 设置页添加Session加载状态处理
在设置页中先判断Session加载状态,避免渲染空数据:
const SettingsPage = () => { const user = useCurrentUser(); const { status } = useSession(); if (status === "loading") { return <div className="text-center py-10">加载中...</div>; } // 原有渲染逻辑... };
内容的提问来源于stack exchange,提问作者EnXan
相关产品推荐
相关产品推荐

