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

如何获取Azure用户访问持久令牌,在WebJob中离线访问用户邮箱

问题根因分析

你遇到的GetAccountAsync返回null是因为两个核心原因:

  • 前端使用的PublicClientApplication(公共客户端)和后端WebJob使用的ConfidentialClientApplication(机密客户端)是完全隔离的MSAL实例,二者的本地令牌缓存、账号信息默认不会跨实例、跨环境同步,后端机密客户端的本地缓存为空,自然查不到对应账号。
  • GetAccountAsync的作用仅为从当前MSAL客户端实例的本地缓存中检索已完成身份验证的账号信息,本身不具备跨实例拉取账号的能力。
解决方案

你已经在前端请求了offline_access权限,这刚好是实现离线访问用户资源的核心权限,不需要申请应用权限,按以下流程实现即可:

  1. 前端调用acquireTokenPopup拿到授权响应后,将响应中的refresh_token、用户账号标识、租户ID等信息加密后传输到后端,存储到你的业务数据库中(refresh_token属于高敏感信息,必须加密存储,禁止明文落盘)。
  2. WebJob中不再调用GetAccountAsync查询账号,直接使用存储的refresh_token兑换有效的access_token调用Microsoft Graph即可,每次兑换新token时MSAL会返回新的refresh_token,同步更新数据库中的存储值即可实现长期有效访问。
代码示例

前端获取refresh_token后传输到后端的逻辑补充

mailApp.acquireTokenPopup(accessTokenRequest).then(accessTokenResponse => {
    // 提取refresh_token、账号信息
    const refreshToken = accessTokenResponse.refreshToken;
    const accountId = accessTokenResponse.account.homeAccountId;
    // 调用后端接口将上述信息加密上传存储
    // ...你的业务逻辑
})

WebJob中兑换access_token的代码

var app = ConfidentialClientApplicationBuilder.Create(ClientId)
    .WithClientSecret(Secret)
    .WithTenantId(Tenant)
    .Build();

// 从数据库中读取对应用户加密存储的refresh_token
string savedRefreshToken = GetRefreshTokenFromDB(accountId); 

var scopes = new[] { "User.Read", "MailboxSettings.Read", "Mail.ReadWrite" };
var tokenResult = await app.AcquireTokenByRefreshToken(scopes, savedRefreshToken)
    .ExecuteAsync();

// 拿到有效的access_token调用Graph即可
string accessToken = tokenResult.AccessToken;
// 兑换成功后将新的refresh_token更新到数据库
UpdateRefreshTokenToDB(accountId, tokenResult.RefreshToken);
注意事项
  • refresh_token的默认有效期最长可达90天,每次兑换新token后都会生成新的refresh_token并重置有效期,只要你每次更新存储的refresh_token,且用户未主动撤销对你应用的授权,就可以长期正常访问。
  • 禁止将refresh_token暴露到前端、日志等非安全区域,存储和传输过程必须做加密处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 21:24:02