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

Next Auth中Session请求暴露Token信息是否属正常行为?

关于NextAuth中/session请求暴露Token的问题解答

1. /session请求的来源

这个请求是NextAuth内置的/api/auth/session端点,作用是在客户端(浏览器)获取当前用户的会话状态。每次页面初始化、调用useSession钩子,或者会话状态可能变更时,NextAuth都会自动发起这个请求,属于框架的正常行为,但绝对不应该返回敏感的Token信息。

2. 你的配置问题

你在session回调中直接将包含accessToken和refreshToken的整个token对象赋值给了session.user,这就导致这些敏感数据被包含在/session请求的响应中,直接暴露给了前端浏览器。尤其是refreshToken,它用于获取新的accessToken,一旦泄露到前端,会带来极高的安全风险。

3. 正确的配置方案

3.1 分离敏感Token与前端会话信息

修改session回调,只将非敏感的用户信息(如邮箱、用户名、ID)返回给前端,严格禁止传递refreshToken;如果前端必须使用accessToken调用后端API,可以选择性返回,但要注意前端的存储安全:

async session({ session, token }) {
  // 只传递前端需要展示或使用的非敏感信息
  session.user = {
    id: token.id,
    email: token.email,
    name: token.name // 假设你的用户对象包含这些字段
  };
  // 仅在前端必须直接调用API时添加accessToken,refreshToken绝对不能放
  session.accessToken = token.accessToken;
  return session;
}

3.2 在服务器端处理Token刷新逻辑

将refreshToken的刷新逻辑放在jwt回调中,由服务器端执行,彻底避免前端接触到refreshToken。示例如下:

async jwt({ token, user, trigger, session }) {
  // 用户登录时,将后端返回的Token信息存入JWT
  if (user) {
    token.accessToken = user.accessToken;
    token.refreshToken = user.refreshToken;
    // 假设后端返回accessToken的过期时间(毫秒时间戳)
    token.accessTokenExpires = user.accessTokenExpires;
  }

  // 提前1分钟检查token是否即将过期,触发刷新
  const isTokenExpired = Date.now() >= token.accessTokenExpires - 60 * 1000;
  if (!isTokenExpired) {
    return token;
  }

  // 调用后端刷新接口获取新的accessToken
  try {
    const refreshResult = await postAPI(
      `${process.env.NEXT_PUBLIC_API_URL}${ApiRoutes.RefreshToken}`,
      { refreshToken: token.refreshToken }
    );
    return {
      ...token,
      accessToken: refreshResult.data.accessToken,
      accessTokenExpires: refreshResult.data.accessTokenExpires
    };
  } catch (error) {
    // 刷新失败,标记错误,后续可引导用户重新登录
    return { ...token, error: "RefreshTokenFailed" };
  }

  // 处理session更新场景(如修改用户信息)
  if (trigger === 'update') {
    return { ...token, ...session.user };
  }

  return token;
}

3.3 前端API调用的安全方式

如果前端需要调用后端API,建议通过NextAuth的getServerSession在服务器端的API路由中获取accessToken,再由服务器端转发请求,让前端完全不接触敏感Token。示例代理路由:

// app/api/proxy/[...path]/route.ts
import { getServerSession } from "next-auth/next";
import { authOptions } from "../../auth/[...nextauth]/route";
import { NextResponse } from "next/server";

export async function GET(request: Request) {
  const session = await getServerSession(authOptions);
  if (!session?.accessToken) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const url = new URL(request.url);
  const targetUrl = `${process.env.NEXT_PUBLIC_API_URL}${url.pathname.replace('/api/proxy', '')}`;

  const response = await fetch(targetUrl, {
    headers: {
      Authorization: `Bearer ${session.accessToken}`
    }
  });

  return NextResponse.json(await response.json());
}

总结

  • /session请求是NextAuth的正常内置请求,但你的配置错误地将敏感Token暴露给了前端。
  • 核心修复点是禁止在session回调中返回refreshToken,并将Token刷新逻辑放在服务器端的jwt回调中。
  • 尽可能通过服务器端代理API调用后端接口,让前端完全不接触敏感Token,大幅提升安全性。

内容的提问来源于stack exchange,提问作者SergioNeves

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 14:57:39