Next.js 14中如何将外部API返回的JWT存入Session?
如何将后端返回的JWT存入NextAuth Session并在客户端组件中便捷访问
当然可以把JWT存入NextAuth Session,这不仅能解决你当前客户端组件难以获取令牌的问题,还能简化认证流程。以下是具体的实现步骤和代码调整方案:
核心思路
NextAuth的jwt和session回调就是用来扩展认证信息的,我们可以把后端返回的JWT令牌(access_token、refresh_token)存入NextAuth的JWT中,再同步到Session,这样客户端组件就能通过useSession钩子直接获取,无需手动传递参数。
代码调整步骤
1. 修改authorize函数,移除手动设置Cookie的逻辑
原来的代码里手动设置了gat和grt Cookie,现在可以去掉这部分,把后端返回的令牌和用户信息一起返回即可,NextAuth会自动处理JWT的存储:
async authorize(credentials) { const { username, password } = credentials as { username: string; password: string; }; const formData = new URLSearchParams(); formData.append("email", encodeURIComponent(username)); formData.append("password", encodeURIComponent(password)); const res = await fetch(loginPath, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", }, body: formData.toString(), }); const receivedToken = await res.json(); if (res.ok && receivedToken) { const parsed = parsePayload(receivedToken.access_token); // 整理要返回的用户信息,包含令牌和解析后的用户数据 return { id: parsed.sub, // 假设JWT payload里有用户ID name: parsed.name, email: username, access_token: receivedToken.access_token, refresh_token: receivedToken.refresh_token, expires_at: parsed.exp // 可选,存入过期时间 }; } else { return null; } }
2. 完善jwt回调,合并令牌信息到NextAuth的JWT
不要直接替换token,而是把用户返回的信息合并进去,避免丢失NextAuth默认的token字段:
jwt: async ({ token, user }) => { // 用户登录时,把后端返回的信息合并到token if (user) { token.id = user.id; token.name = user.name; token.email = user.email; token.access_token = user.access_token; token.refresh_token = user.refresh_token; token.expires_at = user.expires_at; } return token; },
3. 调整session回调,将令牌同步到Session
把JWT中的令牌信息放到session对象里,这样客户端就能获取:
session: async ({ session, token }) => { session.user.id = token.id; session.user.name = token.name; session.user.email = token.email; // 把令牌添加到session,客户端可访问 session.access_token = token.access_token; session.refresh_token = token.refresh_token; session.expires_at = token.expires_at; return session; },
4. 客户端组件中获取令牌
现在可以直接用NextAuth的useSession钩子在客户端组件中获取令牌,无需从服务器组件传递:
"use client"; import { useSession } from "next-auth/react"; export default function ClientComponent() { const { data: session, status } = useSession(); if (status === "loading") { return <div>加载中...</div>; } if (!session) { return <div>请先登录</div>; } // 直接使用session中的令牌 console.log("Access Token:", session.access_token); return ( <div> <p>欢迎,{session.user.name}</p> </div> ); }
可选:保留httpOnly Cookie用于后端API调用
如果你仍需要将access_token存为httpOnly Cookie(比如后端API直接验证Cookie),可以在jwt回调中设置Cookie,同时存入Session:
import { cookies } from "next/headers"; // 在jwt回调中添加 jwt: async ({ token, user }) => { if (user) { // ... 之前的合并逻辑 // 设置httpOnly Cookie cookies().set({ name: "gat", value: user.access_token, httpOnly: true, secure: process.env.NODE_ENV === "production", sameSite: "strict", path: "/", }); cookies().set({ name: "grt", value: user.refresh_token, httpOnly: true, secure: process.env.NODE_ENV === "production", sameSite: "strict", path: "/", }); } return token; },
为什么这是更优方案
- 客户端组件无需依赖服务器组件传递令牌,代码更简洁
- 利用NextAuth的Session管理机制,自动处理会话的持久化和刷新(可扩展refresh_token的自动刷新逻辑)
- 统一认证信息的存储,避免手动管理Cookie的繁琐和潜在错误
内容的提问来源于stack exchange,提问作者diminuta
相关产品推荐
相关产品推荐

