You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 20:40:54