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

基于Azure AD JWT认证,如何无会话获取Microsoft Graph令牌?

解决方案:使用Azure AD的On-Behalf-Of (OBO) 流程

你的场景正好对应Azure AD的**On-Behalf-Of (OBO)**授权流程——这是专门为中间层服务设计的,允许你的应用(已经持有用户的JWT令牌,受众为你的应用ID)代表用户向另一个资源(这里是Microsoft Graph API)请求访问令牌,全程不需要依赖会话缓存,完全符合你无状态JWT的需求。

第一步:确保Azure AD应用的配置正确

在Azure门户的应用注册中完成以下配置:

  • 添加Microsoft Graph的委派权限:比如你需要获取用户数据,可以添加User.Read.All、User.ReadBasic.All等委派权限,记得点击"授予管理员同意"(如果是租户级应用)。
  • 启用客户端凭据:因为你的应用是服务端应用(Confidential Client),需要生成客户端密钥(Client Secret)或者使用证书,用于向Azure AD证明应用身份。
  • 确保应用支持OBO流程:OBO流程是默认支持的,只要你的应用是Confidential Client且有正确的权限配置即可。

第二步:ASP.NET Core中的代码实现

你已经配置了JWT认证并设置SaveToken = true,这意味着用户的访问令牌会被保存到HttpContext中,我们可以直接获取它,然后用OBO流程换取Graph API的令牌。

核心代码示例

在你的控制器或服务中,注入IConfiguration,然后实现令牌换取逻辑:

using Microsoft.Identity.Client;
using Microsoft.AspNetCore.Authentication;

// 注入依赖
private readonly IConfiguration _config;

public YourController(IConfiguration config)
{
    _config = config;
}

public async Task<string> GetGraphAccessToken()
{
    // 1. 从当前请求中获取用户的原始JWT令牌(受众为你的应用)
    var userAccessToken = await HttpContext.GetTokenAsync("access_token");
    if (string.IsNullOrEmpty(userAccessToken))
    {
        throw new UnauthorizedAccessException("无法获取用户的访问令牌");
    }

    // 2. 初始化ConfidentialClientApplication(不需要TokenCache,保持无状态)
    var clientId = _config["AzureAd:ClientId"];
    var clientSecret = _config["AzureAd:ClientSecret"];
    var tenantId = _config["AzureAd:TenantId"];
    var authority = $"https://login.microsoftonline.com/{tenantId}/v2.0";

    var confidentialClient = ConfidentialClientApplicationBuilder
        .Create(clientId)
        .WithClientSecret(clientSecret)
        .WithAuthority(authority)
        .Build();

    // 3. 执行OBO流程,获取Graph API的访问令牌
    var scopes = new[] { "https://graph.microsoft.com/User.Read.All" }; // 根据你的需求调整scopes
    var oboParameters = new OnBehalfOfParameters(scopes, new UserAssertion(userAccessToken));
    
    var result = await confidentialClient.AcquireTokenOnBehalfOfAsync(oboParameters);

    return result.AccessToken;
}

配置文件(appsettings.json)示例

确保你的配置包含必要的参数:

{
  "AzureAd": {
    "ClientId": "你的应用ID",
    "ClientSecret": "你的客户端密钥",
    "TenantId": "你的租户ID",
    "Instance": "https://login.microsoftonline.com/"
  }
}

关键说明

  • 无状态实现:这里没有使用任何令牌缓存(比如SessionTokenCache),每次请求都会向Azure AD发起OBO令牌请求,完全符合你JWT无状态的要求。
  • 令牌受众转换:OBO流程会将受众为你的应用的用户令牌,转换为受众为https://graph.microsoft.com的访问令牌,该令牌可直接用于调用Graph API的用户数据接口。
  • 权限要求:确保你请求的scopes已经在Azure AD应用中配置并获得了管理员同意,否则会返回权限不足的错误。

对比你之前的示例代码

你之前看到的AcquireTokenSilentAsync是用于从缓存中获取已有的令牌,适合会话式应用;而AcquireTokenOnBehalfOfAsync是专门为中间层服务设计的无状态令牌换取方式,完美匹配你的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:18:45