如何将NextAuth的JWT Token传递至Express后端并保护API路由
NextAuth JWT Token传递至Express后端实现API路由保护
我开发了一个基于Next.js的应用,使用NextAuth实现登录功能,后端采用Express.js。请问在前端发起API请求时,如何将NextAuth生成的JWT Token放入请求头中传递给Express后端,以实现API路由的保护?我不清楚如何将JWT Token返回至session中以便用于API请求,以下是我的NextAuth路由代码:
export const authOptions = { adapter: PrismaAdapter(prisma), providers: [ CredentialsProvider({ name: "credentials", credentials: { password: { label: "Password", type: "password" }, email: { label: "Email", type: "email" }, }, async authorize(credentials) { // Check if getting credentials if (!credentials.email || !credentials.password) { throw new Error("err"); } // Check if user exist const user = await prisma.user.findUnique({ where: { email: credentials.email }, }); if (!user) { throw new Error( "err" ); } // Check if password match const passwordMatch = await bcrypt.compare( credentials.password, user.hashedPassword ); if (!passwordMatch) { throw new Error( "err" ); } // Return user object return { id: user._id, email: user.email, role: user.role }; }, }), ], callbacks: { async session({ token, session }) { if (token) { session.user.id = token.id; session.user.email = token.email; session.user.role = token.role; } return session; }, async jwt({ token, user }) { const dbUser = await prisma.user.findFirst({ where: { email: token.email }, }); if (!user) { token.id = user && user.id; return token; } return { id: dbUser.id, email: dbUser.email, role: dbUser.role, }; }, }, session: { strategy: "jwt", }, secret: process.env.NEXTAUTH_SECRET, debug: process.env.NODE_ENV !== "production", }; const handler = NextAuth(authOptions);
解决方案
1. 修改NextAuth配置,将原始JWT Token加入Session
默认情况下useSession返回的session不包含原始JWT字符串,需要在session回调中手动添加。借助NextAuth的getToken方法获取原始Token并挂载到session对象:
首先导入getToken:
import { getToken } from "next-auth/jwt";
然后修正并更新callbacks中的session和jwt回调:
callbacks: { async session({ session, req }) { // 获取未解码的原始JWT字符串 const rawToken = await getToken({ req, secret: process.env.NEXTAUTH_SECRET, raw: true }); if (rawToken) { // 将原始Token加入session供前端使用 session.accessToken = rawToken; // 保留用户信息 const decodedToken = await getToken({ req, secret: process.env.NEXTAUTH_SECRET }); session.user.id = decodedToken.id; session.user.email = decodedToken.email; session.user.role = decodedToken.role; } return session; }, async jwt({ token, user }) { // 用户首次登录时,从数据库获取完整信息 if (user) { const dbUser = await prisma.user.findUnique({ where: { email: user.email }, }); return { id: dbUser.id, email: dbUser.email, role: dbUser.role, }; } // 后续请求更新Token中的用户信息,避免数据过期 const dbUser = await prisma.user.findUnique({ where: { email: token.email }, }); if (dbUser) { token.id = dbUser.id; token.email = dbUser.email; token.role = dbUser.role; } return token; }, },
2. 前端发起API请求时携带Token
使用useSession钩子获取session中的accessToken,将其放入请求头的Authorization字段:
import { useSession } from "next-auth/react"; async function fetchProtectedData() { const { data: session } = useSession(); // 未登录时直接返回 if (!session?.accessToken) return; try { const response = await fetch("http://你的Express后端地址/protected-route", { method: "GET", headers: { "Authorization": `Bearer ${session.accessToken}`, "Content-Type": "application/json" } }); if (!response.ok) throw new Error("请求失败"); const data = await response.json(); // 处理返回的数据 } catch (err) { console.error(err); } }
3. Express后端验证JWT Token
使用jsonwebtoken库验证Token,确保使用和NextAuth相同的NEXTAUTH_SECRET:
首先安装依赖:
npm install jsonwebtoken
然后编写验证中间件和受保护路由:
const jwt = require("jsonwebtoken"); require("dotenv").config(); // JWT验证中间件 function authenticateToken(req, res, next) { const authHeader = req.headers.authorization; const token = authHeader?.split(" ")[1]; // 提取Bearer后的Token if (!token) { return res.sendStatus(401); // 未提供Token,返回未授权 } jwt.verify(token, process.env.NEXTAUTH_SECRET, (err, decodedUser) => { if (err) { return res.sendStatus(403); // Token无效或过期,返回禁止访问 } req.user = decodedUser; // 将用户信息挂载到请求对象 next(); }); } // 受保护的API路由 app.get("/protected-route", authenticateToken, (req, res) => { res.json({ message: "这是受保护的数据", user: req.user }); });
内容的提问来源于stack exchange,提问作者Nikolay Clutchkin
相关产品推荐
相关产品推荐

