从Blazor WebAssembly调用Azure Functions受保护API遇401问题求助
解决方案:Blazor WASM 调用 AAD B2B 保护的 Azure Functions 401 问题
核心配置排查(最可能的遗漏点)
1. 令牌受众精确匹配
- 确认Azure Functions的应用服务认证设置中,
Allowed Token Audiences严格匹配自定义应用ID URI(api://NAME),注意大小写、是否带末尾斜杠——AAD受众校验为精确匹配,任何差异都会导致401。 - 用本地JWT解析工具检查Blazor获取的
accessToken:查看aud声明是否等于api://NAME,若为应用注册的clientId,说明Scope配置错误。
2. Scope配置必须完整
Blazor请求令牌时,Scope必须是完整权限路径(api://NAME/user_impersonation),而非仅user_impersonation。AAD要求自定义API的Scope必须包含应用ID URI前缀。
修正后的代码示例:
builder.Services.AddMsalAuthentication(options => { builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication); // 明确指定完整Scope路径 options.ProviderOptions.DefaultAccessTokenScopes.Add("api://NAME/user_impersonation"); })
同步确认appsettings.json中AzureAd:Scopes值为完整路径。
3. CORS配置必须允许凭据
- Azure静态网站CORS设置:允许来源为Blazor域名(如
https://your-static-site.azurestaticapps.net),并勾选允许凭据(AAD认证令牌需携带凭据头)。 - Azure Functions的CORS设置需与静态网站保持一致,避免规则冲突。
认证流程正确实现
1. 令牌附加的标准方式
Blazor WASM需通过IAccessTokenProvider获取令牌(自动处理缓存与刷新),而非手动读取存储。仅使用Authorization: Bearer <token>头——X-ZUMO-AUTH为旧Azure Mobile Apps专用头,Azure Functions不支持:
private readonly HttpClient _httpClient; private readonly IAccessTokenProvider _tokenProvider; public ApiService(HttpClient httpClient, IAccessTokenProvider tokenProvider) { _httpClient = httpClient; _tokenProvider = tokenProvider; } public async Task<HttpResponseMessage> CallProtectedEndpoint() { var tokenResult = await _tokenProvider.RequestAccessToken(new AccessTokenRequestOptions { Scopes = new[] { "api://NAME/user_impersonation" } }); if (tokenResult.TryGetToken(out var token)) { _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Value); return await _httpClient.GetAsync("https://your-functions-api.azurewebsites.net/api/your-endpoint"); } // 处理令牌获取失败(如引导重新登录) return new HttpResponseMessage(HttpStatusCode.Unauthorized); }
2. 双应用注册的权限配置(若使用)
若客户端与API分别注册应用:
- API应用注册:暴露
user_impersonation权限,应用ID URI设为api://NAME。 - 客户端应用注册:在API权限中添加API应用的
user_impersonation权限,并授予管理员同意(B2B场景必须,否则外部用户无法获取权限)。 - Blazor的
AzureAd配置使用客户端应用的ClientId,而非API应用的。
进程外Azure Functions特殊配置
进程外托管模式下,需在host.json中显式配置认证受众,避免应用服务认证设置未同步:
{ "version": "2.0", "authentication": { "azureActiveDirectory": { "clientId": "YOUR-FUNCTIONS-APP-REG-CLIENT-ID", "allowedAudiences": [ "api://NAME" ] } } }
最终验证步骤
- 解析
accessToken,确认aud为api://NAME、scp包含user_impersonation。 - 查看Azure Functions的认证日志(门户->Functions->认证->日志),获取401的具体原因(如受众不匹配、权限不足、令牌过期)。
- 确认B2B用户已被邀请至租户,且首次登录时已同意应用权限。
内容的提问来源于stack exchange,提问作者Federico Rapetti
相关产品推荐
相关产品推荐

