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

Next.js API路由及服务器组件中AccessToken无法访问问题

问题:NextAuth + Azure AD 场景下的 Token 访问问题

我用NextAuth结合Azure AD做登录提供商,登录功能正常。目前遇到两个核心问题:

  • 在NextAuth的callbacks里能拿到access_token,middleware.ts里用getToken也能正常获取,但内部API路由里调用getToken始终返回null,req.cookies.getAll()也拿不到任何数据;
  • 想在服务器组件里访问access_token,但服务器组件没有request对象,不知道怎么操作。

已尝试的解决方案

auth.js 配置

callbacks: {
    async jwt({ token, account }) {
        if (account) {
            token.accessToken = account.access_token
          }
          return token
    },
    async session({ session, token }) {
        session.token = token.accessToken ?? "No token found";
        return session; // 期望在服务器组件中可用
    },
    async redirect() {
        return "/";
    }
}

page.tsx(服务器组件)

export default async function Page() {
  const session = await getServerSession(authOptions)
  const token = session?.token;
  return <pre>{session?.token}</pre>
}

next-auth-d.ts(类型声明)

import NextAuth, { DefaultSession } from "next-auth";
import type { Session, Account,JWT } from "next-auth";

declare module "next-auth" {
  interface JWT {
    accessToken?: accessToken;
    user: {
      token?: accessToken;
    } & DefaultSession["user"];
  }
  interface Session {
    token?: accessToken;
    user: {
      token?: accessToken;
    } & DefaultSession["user"];
  }
  interface Account {
    access_token: accessToken;
    user: {
      token?: accessToken;
    } & DefaultSession["user"];
  }
}

补充说明

官方文档标注此为预期行为,但我仍不清楚如何在服务器组件中获取token。


我的当前配置代码

AuthConfig(authOptions)

import { NextAuthOptions } from "next-auth";
import AzureADProvider from "next-auth/providers/azure-ad";
import { CLIENT_ID, CLIENT_SECRET, TENANT_ID } from "./utils/envPublic";

const authOptions: NextAuthOptions = {
    providers: [
        AzureADProvider({
            clientId: CLIENT_ID,
            clientSecret: CLIENT_SECRET,
            tenantId: TENANT_ID,
            authorization: {
                params: {
                    scope: "openid profile email api://myapi/my.scope",
                }
            }
        })
    ],
    secret: process.env.NEXTAUTH_SECRET,
    session: {
        strategy: "jwt"
    },
    jwt: {
        secret: process.env.NEXTAUTH_SECRET
    },
    callbacks: {
        async jwt({ token, account, user }) {
            token.accessToken = account?.access_token;
            return { ...token, ...user, ...account };
        },
        async session({ session, token, user }) {
            session.token = token.accessToken;
            session.user.token = token.accessToken;
            return session;
        },
        async redirect() {
            return "/"
        }
    },
};

export default authOptions;

API 路由(app/api/xxx/route.ts)

import { getToken } from 'next-auth/jwt';
import { NextRequest, NextResponse } from 'next/server';

export const GET = async (req: NextRequest) => {
    
    const token = await getToken({ req: req, secret: process.env.SECRET })
    console.log("token from API:")
    console.log(token); // 始终返回null

    const cookies = req.cookies.getAll();
    console.log("cookies from API:")
    console.log(cookies.length); // 始终返回0

    const response = await fetch('https://jsonplaceholder.typicode.com/todos/1')
    const json = await response.json();

    return NextResponse.json(json);
}

middleware.ts

import { getToken } from 'next-auth/jwt'
import type { NextRequest, NextResponse } from 'next/server'

export async function middleware(request: NextRequest) {
    const token = await getToken({ req: request, secret: process.env.SECRET });
    console.log("token:");
    console.log(token); // 能正常打印正确的token
}

解决方案

问题1:API路由无法获取Token的修复

你在API路由里调用getToken时误用了process.env.SECRET,NextAuth的JWT验证必须使用和authOptions中一致的NEXTAUTH_SECRET。另外,客户端调用API时需确保请求携带Cookie凭证。

修改后的API路由代码:

import { getToken } from 'next-auth/jwt';
import { NextRequest, NextResponse } from 'next/server';
import authOptions from '@/path/to/your/authOptions'; // 导入你的authOptions

export const GET = async (req: NextRequest) => {
    // 使用authOptions中的统一secret,避免环境变量不一致
    const token = await getToken({ req, secret: authOptions.secret })
    console.log("token from API:", token);

    const response = await fetch('https://jsonplaceholder.typicode.com/todos/1')
    const json = await response.json();

    return NextResponse.json(json);
}

客户端调用API时需添加凭证配置:

// 客户端组件内调用示例
const fetchData = async () => {
  const res = await fetch('/api/xxx', { credentials: 'include' });
  const data = await res.json();
}

问题2:服务器组件中访问access_token的方法

你的思路是对的,通过getServerSession获取session再提取token,但需修正类型声明并确保getServerSession正确传入authOptions。

修正类型声明(next-auth-d.ts)

补充未定义的AccessToken类型,精简冗余声明:

import NextAuth, { DefaultSession } from "next-auth";
import type { Session, Account,JWT } from "next-auth";

type AccessToken = string;

declare module "next-auth" {
  interface JWT {
    accessToken?: AccessToken;
  }
  interface Session {
    token?: AccessToken;
    user: {
      token?: AccessToken;
    } & DefaultSession["user"];
  }
  interface Account {
    access_token: AccessToken;
  }
}

服务器组件正确获取Token

确保导入正确的getServerSession并传入authOptions:

import { getServerSession } from "next-auth/next";
import authOptions from "@/path/to/your/authOptions";

export default async function Page() {
  const session = await getServerSession(authOptions);
  const accessToken = session?.token;

  return <div>{accessToken ? `Token: ${accessToken}` : "未登录"}</div>;
}

额外注意事项

  • 确保NEXTAUTH_SECRET环境变量在所有环境中配置一致;
  • App Router下getServerSession需从next-auth/next导入,而非next-auth/react;
  • 受保护的API路由建议用Middleware提前拦截未登录请求,避免无效调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 13:54:54