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

Blazor WebAssembly独立应用获取多AAD保护API令牌及调用疑问

解决Blazor WASM MSAL多范围令牌获取问题

我明白你遇到的困扰——Angular里MSAL能自动搞定多API的令牌获取和请求拦截,但Blazor WASM的MSAL配置确实需要更明确的设置才能支持多个不同AD App API的令牌获取。下面是具体的解决方案:

核心原因

Blazor的AddMsalAuthentication默认只为单个API(即你配置的ClientId对应的API)处理令牌获取,当你添加多个跨不同AD App的范围时,它不会自动为每个API单独请求令牌。要实现类似Angular的自动拦截匹配,需要为每个API单独配置HttpClient并绑定对应的范围。

方案1:配置命名HttpClient(推荐,类似Angular自动拦截)

通过IHttpClientFactory为每个API创建命名的HttpClient实例,每个实例绑定对应的授权范围和API地址,这样发送请求时会自动获取并附加正确的令牌。

配置代码

在Program.cs中添加以下配置(替换你的API地址和范围):

builder.Services.AddMsalAuthentication(options => { 
    var config = options.ProviderOptions; 
    config.Authentication.Authority = "https://login.microsoftonline.com/tenantID"; 
    config.Authentication.ClientId = "clientID"; 
    options.ProviderOptions.DefaultAccessTokenScopes.Add("offline_access"); 
});

// 配置Graph API的专属HttpClient
builder.Services.AddHttpClient("GraphAPI", client =>
{
    client.BaseAddress = new Uri("https://graph.microsoft.com/");
})
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>()
.AddHttpMessageHandler(sp =>
{
    var handler = sp.GetRequiredService<BaseAddressAuthorizationMessageHandler>()
        .ConfigureHandler(
            authorizedUrls: new[] { "https://graph.microsoft.com/" },
            scopes: new[] { "https://graph.microsoft.com/user.read" });
    return handler;
});

// 配置Dynamics CRM的专属HttpClient
builder.Services.AddHttpClient("DynamicsCRM", client =>
{
    client.BaseAddress = new Uri("https://tenant.crm.dynamics.com/");
})
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>()
.AddHttpMessageHandler(sp =>
{
    var handler = sp.GetRequiredService<BaseAddressAuthorizationMessageHandler>()
        .ConfigureHandler(
            authorizedUrls: new[] { "https://tenant.crm.dynamics.com/" },
            scopes: new[] { "https://tenant.crm.dynamics.com/user_impersonation" });
    return handler;
});

// 配置自定义API的专属HttpClient
builder.Services.AddHttpClient("CustomAPI", client =>
{
    client.BaseAddress = new Uri("https://your-custom-api-url/");
})
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>()
.AddHttpMessageHandler(sp =>
{
    var handler = sp.GetRequiredService<BaseAddressAuthorizationMessageHandler>()
        .ConfigureHandler(
            authorizedUrls: new[] { "https://your-custom-api-url/" },
            scopes: new[] { "clientID/scope1" });
    return handler;
});

在页面中使用

注入IHttpClientFactory,创建对应命名的HttpClient即可自动携带正确令牌:

@inject IHttpClientFactory HttpClientFactory

<button @onclick="FetchGraphData">获取Graph用户数据</button>
<button @onclick="FetchCrmData">获取Dynamics CRM账户数据</button>

@code {
    private async Task FetchGraphData()
    {
        var graphClient = HttpClientFactory.CreateClient("GraphAPI");
        var userData = await graphClient.GetFromJsonAsync<dynamic>("me");
        // 处理数据
    }

    private async Task FetchCrmData()
    {
        var crmClient = HttpClientFactory.CreateClient("DynamicsCRM");
        var accounts = await crmClient.GetFromJsonAsync<dynamic>("/api/data/v9.2/accounts");
        // 处理数据
    }
}

方案2:手动获取令牌(灵活场景)

如果需要更灵活的控制(比如动态切换范围),可以使用IAccessTokenAcquisition服务手动获取指定范围的令牌,然后附加到请求头中:

@inject HttpClient HttpClient
@inject IAccessTokenAcquisition TokenAcquisition

<button @onclick="FetchCrmDataManual">手动获取令牌请求CRM</button>

@code {
    private async Task FetchCrmDataManual()
    {
        // 获取Dynamics CRM的令牌
        var crmToken = await TokenAcquisition.GetAccessTokenForUserAsync(
            new[] { "https://tenant.crm.dynamics.com/user_impersonation" });

        // 创建请求并添加授权头
        var request = new HttpRequestMessage(
            HttpMethod.Get, 
            "https://tenant.crm.dynamics.com/api/data/v9.2/accounts");
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", crmToken);

        var response = await HttpClient.SendAsync(request);
        response.EnsureSuccessStatusCode();
        var accounts = await response.Content.ReadFromJsonAsync<dynamic>();
        // 处理数据
    }
}

注意事项

  • 确保每个AD App的API都已在Azure AD中配置了正确的范围,且Blazor客户端ID已获得对应的权限(管理员同意或用户同意)。
  • offline_access范围不需要单独绑定到HttpClient,它是用于刷新令牌的,配置在DefaultAccessTokenScopes中即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 00:17:36