如何使用MSAL从.NET MAUI应用调用Azure AD B2C认证的API
使用MSAL实现.NET MAUI对Azure AD B2C保护的API调用
核心思路:让MSAL自动管理令牌并注入请求头
MSAL的AcquireTokenSilent方法会自动处理令牌的获取与刷新,配合HttpClient的委托处理程序,就能实现请求头的自动注入,完全替代手动添加Bearer token的操作。
步骤1:初始化MSAL客户端
确保.NET MAUI项目中MSAL客户端配置包含目标API的权限范围(格式通常为https://{租户名}.b2clogin.com/{租户名}.onmicrosoft.com/api/{权限名}):
var pca = PublicClientApplicationBuilder .Create("你的客户端ID") .WithB2CAuthority("https://{租户名}.b2clogin.com/tfp/{租户名}.onmicrosoft.com/{你的B2C策略名}") .WithRedirectUri("msal{客户端ID}://auth") // .NET MAUI默认重定向URI .Build();
步骤2:实现令牌注入的Http委托处理器
自定义DelegatingHandler,在请求发送前自动获取令牌并添加到授权头:
public class MsalAuthHandler : DelegatingHandler { private readonly IPublicClientApplication _pca; private readonly string[] _apiScopes; public MsalAuthHandler(IPublicClientApplication pca, string[] apiScopes) { _pca = pca; _apiScopes = apiScopes; } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var accounts = await _pca.GetAccountsAsync(); var currentAccount = accounts.FirstOrDefault(); if (currentAccount != null) { try { // 静默获取令牌,MSAL自动处理过期刷新 var tokenResult = await _pca.AcquireTokenSilent(_apiScopes, currentAccount) .ExecuteAsync(cancellationToken); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokenResult.AccessToken); } catch (MsalUiRequiredException) { // 静默获取失败(如令牌过期且无法刷新、会话失效),触发交互式登录 var interactiveResult = await _pca.AcquireTokenInteractive(_apiScopes) .WithAccount(currentAccount) .ExecuteAsync(cancellationToken); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", interactiveResult.AccessToken); } } return await base.SendAsync(request, cancellationToken); } }
步骤3:注册服务与HttpClient
在MauiProgram.cs中,将MSAL客户端和自定义处理器注册为依赖注入服务:
builder.Services.AddSingleton<IPublicClientApplication>(sp => { return PublicClientApplicationBuilder .Create("你的客户端ID") .WithB2CAuthority("https://{租户名}.b2clogin.com/tfp/{租户名}.onmicrosoft.com/{你的B2C策略名}") .WithRedirectUri("msal{客户端ID}://auth") .Build(); }); builder.Services.AddHttpClient("ProtectedApiClient", client => { client.BaseAddress = new Uri("你的API基础地址/"); }) .AddHttpMessageHandler(sp => { var pca = sp.GetRequiredService<IPublicClientApplication>(); var apiScopes = new[] { "https://{租户名}.b2clogin.com/{租户名}.onmicrosoft.com/api/access_as_user" }; return new MsalAuthHandler(pca, apiScopes); });
步骤4:调用API(GET/POST示例)
通过依赖注入获取命名HttpClient,直接发起请求即可,无需手动处理令牌:
private readonly IHttpClientFactory _httpClientFactory; public YourViewModel(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } // GET请求示例 public async Task FetchApiDataAsync() { var client = _httpClientFactory.CreateClient("ProtectedApiClient"); var response = await client.GetAsync("api/你的接口路径"); if (response.IsSuccessStatusCode) { var data = await response.Content.ReadFromJsonAsync<你的数据模型>(); // 处理返回数据 } } // POST请求示例 public async Task SubmitDataAsync(你的数据模型 model) { var client = _httpClientFactory.CreateClient("ProtectedApiClient"); var response = await client.PostAsJsonAsync("api/你的接口路径", model); if (response.IsSuccessStatusCode) { // 处理成功逻辑 } }
关键注意事项
- 权限配置:确保Azure AD B2C中已为API注册对应权限,且客户端应用已被授予该权限。
- 异常处理:
MsalUiRequiredException是核心异常,需在此处触发交互式登录流程,引导用户重新认证。 - 令牌缓存:MSAL会自动维护令牌缓存,包括刷新令牌的使用,无需手动存储或管理。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

