Blazor Server调用Azure AD认证的.NET 6 API返回401未授权问题
Blazor Server + Azure AD + .NET6 API 401 问题排查指南
一、先查Azure AD应用注册的核心配置
- 权限与同意:Blazor应用的注册必须拥有API应用的委派权限,且已完成管理员同意。若使用自定义API权限,需确认API应用
Expose an API中的Scope配置正确,且Blazor请求Token时已携带该Scope。 - 受众(Audience)匹配:API的
appsettings.json中AzureAd.ClientId要和API应用注册的Application (client) ID完全一致。用jwt.ms解析传入API的Token,查看aud声明是否等于该ClientId;若API使用自定义Scope,aud也可能是API的Application ID URI,此时配置里需添加Audience字段对应该URI。 - Issuer一致性:API配置的
Authority格式需正确(如https://login.microsoftonline.com/{tenantId}/v2.0),同时Token的iss声明要与该Authority完全匹配,避免混用v1和v2端点格式。
二、API项目配置踩坑点
appsettings.json 关键参数核对
确保AzureAD节点参数无错误:
"AzureAd": { "Instance": "https://login.microsoftonline.com/", "Domain": "你的租户域名.onmicrosoft.com", "TenantId": "租户GUID", "ClientId": "API应用的ClientID", "Audience": "api://API应用的ClientID" // 使用自定义Scope时填API的Application ID URI }
若API采用v2端点,可添加"AllowWebApiToBeAuthorizedByACL": true,部分场景下可解决验证异常。
Program.cs 中间件配置
.NET6中中间件顺序错误会直接导致验证失败,严格按以下顺序配置:
var builder = WebApplication.CreateBuilder(args); // 添加身份验证服务 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd")); // 添加授权服务 builder.Services.AddAuthorization(); var app = builder.Build(); // 中间件顺序不可调换:UseRouting之后,UseEndpoints之前 app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
若需验证自定义Scope,需在AddMicrosoftIdentityWebApi中明确配置:
.AddMicrosoftIdentityWebApi(options => { builder.Configuration.Bind("AzureAd", options); options.TokenValidationParameters.ValidAudience = "api://你的API ClientID"; options.TokenValidationParameters.ValidIssuer = "https://login.microsoftonline.com/你的租户ID/v2.0"; }, options => builder.Configuration.Bind("AzureAd", options));
三、Blazor端获取正确的API Token
Blazor自身的登录Token无法直接用于API调用,需获取针对API的专用Token:
- 在Blazor的
Program.cs中配置API的Scope:
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd") .EnableTokenAcquisitionToCallDownstreamApi(new[] { "api://你的API ClientID/access_as_user" }) .AddInMemoryTokenCaches();
- 在Blazor组件中获取Token时,需指定对应Scope:
var token = await _tokenAcquisition.GetAccessTokenForUserAsync(new[] { "api://你的API ClientID/access_as_user" }); // 将Token放入请求头:Authorization: Bearer {token}
解析获取到的Token,确认scp声明中包含API所需权限,否则API会拒绝验证。
四、Token验证细节深挖
- 用jwt.ms解析传入API的Token,重点检查以下字段:
aud:必须与API配置的Audience或ClientId完全一致。iss:与API的Authority匹配。exp:Token未过期。scp/roles:若控制器使用[Authorize(Roles = "xxx")]或自定义策略,Token中需包含对应声明。
- 开启API调试日志,查看具体报错原因:在
appsettings.json中添加日志配置:
"Logging": { "LogLevel": { "Microsoft.AspNetCore.Authentication": "Debug", "Microsoft.Identity.Web": "Debug" } }
启动API后查看日志,会明确输出Token验证失败的具体原因(如受众不匹配、Issuer无效、权限不足等)。
五、控制器代码检查
- 避免给需要授权的控制器/方法错误添加
[AllowAnonymous]特性;若[Authorize]中指定了角色或策略,需确认Token中包含对应声明(如[Authorize(Roles = "Admin")]需Token带有roles声明且值为Admin)。
内容的提问来源于stack exchange,提问作者Dag Eian
相关产品推荐
相关产品推荐

