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

如何在NextJS项目中通过NextAuth获取JWT令牌用于后续API调用?

解决NextAuth.js(Credentials Provider)获取JWT令牌的问题

核心问题分析

你遇到的问题根源有两个:

  1. Credentials Provider的token传递逻辑和OAuth不同:OAuth的account对象会自带accessToken,但Credentials模式下,需要你在authorize函数中手动把私有API返回的JWT挂载到返回的user对象上,才能在jwt回调中拿到。
  2. 未处理sessionData的状态问题:useSession返回的sessionData在loading或unauthenticated状态下是undefined,直接解构会报错。

分步解决方案

1. 修正Credentials Provider的authorize函数

在api/auth/[...nextauth].ts中,确保登录成功后把私有API返回的JWT包含在返回的用户对象里:

import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";

export default NextAuth({
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        // 根据你的登录字段调整,比如username/password
        username: { label: "Username", type: "text" },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials) {
        // 调用私有API完成登录
        const res = await fetch("https://your-private-api/login-endpoint", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(credentials),
        });

        const loginResult = await res.json();

        // 登录成功时,返回包含accessToken的用户对象
        if (res.ok && loginResult.accessToken) {
          return {
            id: loginResult.userId, // 可选,根据你的API返回调整
            name: loginResult.username, // 可选
            accessToken: loginResult.accessToken, // 关键:把私有API的JWT带回去
          };
        }

        // 登录失败返回null
        return null;
      },
    }),
  ],
  // 必须设置session策略为jwt,否则无法通过回调传递token
  session: { strategy: "jwt" },
  // 修正jwt和session回调逻辑
  callbacks: {
    async jwt({ token, user }) {
      // 登录时,user是authorize返回的对象,包含accessToken
      if (user) {
        token.accessToken = user.accessToken;
      }
      return token;
    },
    async session({ session, token }) {
      // 将token中的accessToken注入到session中,供客户端使用
      session.accessToken = token.accessToken;
      return session;
    },
  },
});

2. 客户端安全获取accessToken

使用useSession时,先判断状态,避免sessionData为undefined的情况:

import { useSession } from "next-auth/react";

function YourComponent() {
  const { data: sessionData, status } = useSession();

  // 处理加载状态
  if (status === "loading") {
    return <div>加载中...</div>;
  }

  // 未登录状态
  if (status === "unauthenticated") {
    return <div>请先登录</div>;
  }

  // 登录后安全获取accessToken
  const accessToken = sessionData?.accessToken;

  // 调用私有API时携带token
  const callPrivateAPI = async () => {
    const res = await fetch("https://your-private-api/protected-endpoint", {
      headers: {
        Authorization: `Bearer ${accessToken}`,
      },
    });
    const data = await res.json();
    // 处理返回数据
  };

  return (
    <div>
      <button onClick={callPrivateAPI}>调用私有API</button>
    </div>
  );
}

export default YourComponent;

3. 优化TypeScript类型(可选但推荐)

避免使用any,定义扩展类型确保类型安全:

// 在项目根目录创建next-auth.d.ts文件
import type { DefaultSession, DefaultJWT } from "next-auth";

declare module "next-auth" {
  interface Session extends DefaultSession {
    accessToken?: string;
  }

  interface User {
    accessToken?: string;
  }
}

declare module "next-auth/jwt" {
  interface JWT extends DefaultJWT {
    accessToken?: string;
  }
}

关键注意点

  • 必须设置session: { strategy: "jwt" },否则jwt和session回调不会生效。
  • 不要依赖account对象传递token,Credentials模式下account的结构和OAuth不同,优先从authorize返回的user对象中获取。
  • 始终通过status判断登录状态,再访问sessionData,避免解构undefined的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 03:15:50