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

next-auth结合Microsoft Graph API:accessToken获取与续期咨询

解决方案与代码示例

1. 正确获取Microsoft Graph API的Access Token

你不需要使用idp_access_token,应该直接使用accounts表中存储的access_token本身。从你提供的JWT解码内容来看,该token已经包含scp: mail.send权限,说明它是专门用于调用Microsoft Graph API的有效令牌。idp_access_token是身份提供商(此处为live.com)的令牌,仅用于与身份提供商的交互,无法直接调用Graph API。

2. 自动刷新过期的Access Token

next-auth的Azure AD B2C Provider会自动处理令牌刷新逻辑,前提是你满足两个条件:

  • 在Azure AD B2C应用配置中启用离线访问权限(offline_access scope)
  • next-auth配置中正确包含该scope

当access_token过期时,next-auth会自动使用refresh_token获取新令牌,并更新accounts表中的记录,无需手动编写刷新逻辑。


完整代码示例

第一步:完善next-auth的Azure AD B2C配置

在[...nextauth].js中,确保scope包含mail.send和offline_access:

import NextAuth from "next-auth"
import AzureADB2CProvider from "next-auth/providers/azure-ad-b2c"

export default NextAuth({
  providers: [
    AzureADB2CProvider({
      tenantId: process.env.AZURE_AD_B2C_TENANT_ID,
      clientId: process.env.AZURE_AD_B2C_CLIENT_ID,
      clientSecret: process.env.AZURE_AD_B2C_CLIENT_SECRET,
      primaryUserFlow: "B2C_1_signupsignin",
      authorization: {
        params: {
          scope: "openid profile email offline_access https://your-tenant-name.onmicrosoft.com/api/mail.send"
          // 注意:Graph权限的scope格式需遵循Azure AD B2C要求,格式为https://{tenant}.onmicrosoft.com/{api-id}/{scope}
        }
      }
    })
  ],
  session: {
    strategy: "jwt" // 使用JWT策略便于令牌管理
  },
  callbacks: {
    async jwt({ token, account }) {
      // 首次登录时保存令牌信息到JWT
      if (account) {
        token.accessToken = account.access_token
        token.refreshToken = account.refresh_token
        token.expiresAt = account.expires_at * 1000 // 转换为毫秒时间戳
      }
      // 令牌未过期则直接返回,next-auth会自动处理过期刷新
      if (Date.now() < token.expiresAt) {
        return token
      }
      return token
    },
    async session({ session, token }) {
      // 将access_token传入前端session(如需在前端调用API)
      session.user.accessToken = token.accessToken
      return session
    }
  }
})

第二步:封装Microsoft Graph Client工具类

在utils/graphClient.js中创建可复用的Graph客户端:

import { Client } from "@microsoft/microsoft-graph-client"
import { TokenCredentialAuthenticationProvider } from "@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials"

// 自定义凭证类,传递next-auth获取的accessToken
class AccessTokenCredential {
  constructor(accessToken) {
    this.accessToken = accessToken
  }

  async getToken() {
    return {
      token: this.accessToken,
      expiresOnTimestamp: Date.now() + 3600 * 1000 // 有效期可根据实际token的exp字段调整
    }
  }
}

export async function createGraphClient(accessToken) {
  const credential = new AccessTokenCredential(accessToken)
  const authProvider = new TokenCredentialAuthenticationProvider(credential, {
    scopes: ["https://graph.microsoft.com/.default"]
  })

  return Client.initWithMiddleware({
    authProvider
  })
}

第三步:在API路由中调用Graph API发送邮件

在pages/api/send-email.js中实现邮件发送逻辑:

import { getServerSession } from "next-auth/next"
import { authOptions } from "./auth/[...nextauth]"
import { createGraphClient } from "../../utils/graphClient"

export default async function handler(req, res) {
  if (req.method !== "POST") {
    return res.status(405).json({ message: "Method not allowed" })
  }

  // 获取当前用户的session,包含最新的accessToken
  const session = await getServerSession(req, res, authOptions)
  if (!session || !session.user.accessToken) {
    return res.status(401).json({ message: "Unauthorized" })
  }

  try {
    const graphClient = await createGraphClient(session.user.accessToken)
    // 调用Graph API发送邮件
    await graphClient.api("/me/sendMail").post({
      message: {
        subject: "邮件营销测试",
        body: {
          contentType: "Text",
          content: "这是一封通过自动化工具发送的测试邮件"
        },
        toRecipients: [
          {
            emailAddress: {
              address: "recipient@example.com"
            }
          }
        ]
      },
      saveToSentItems: true
    })

    return res.status(200).json({ message: "邮件发送成功" })
  } catch (error) {
    console.error("发送邮件失败:", error)
    return res.status(500).json({ message: "发送邮件失败", error: error.message })
  }
}

关键注意事项

  • 确保Azure AD B2C的API应用已正确配置Microsoft Graph API的mail.send权限,并完成管理员同意授权。
  • offline_access scope是实现令牌自动刷新的核心,必须包含在next-auth的scope配置中。
  • 建议使用getServerSession在服务器端获取令牌,避免在前端暴露敏感的access_token。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 00:55:54