Blazor Server基于Azure AD调用RequireAuthorization保护的下游API返回401
使用DownstreamApi调用通过endpoint.map构建并添加RequireAuthorization保护的API时返回401未授权,技术栈为.NET6、Azure AD、Blazor Server。已完成官方配置流程,调用带Authorize特性的控制器API正常,但极简API无法通过授权。已知DownstreamApi会自动添加访问令牌,求解决方法。
待调用API配置
Startup.cs:
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Identity.Web; namespace WebApi { public class Startup { public IConfiguration Configuration { get; } public Startup(IConfiguration configuration) { Configuration = configuration; } public void ConfigureServices(IServiceCollection services) { var configuration = new ConfigurationBuilder() .AddJsonFile("appsettings.json") .Build(); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(Configuration); services.AddControllers(); } public void Configure(IApplicationBuilder app) { app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); // 调用此端点返回401 app.UseEndpoints(endpoints => { endpoints.Map("/api/mytodo", (context) => context.Response.WriteAsync("success") ).RequireAuthorization(); }); // 原控制器API可正常调用 app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } }
appsettings.json:
{ "AzureAd": { "Instance": "https://login.microsoftonline.com/", "Domain": " --- cut ---- .onmicrosoft.com", "TenantId": "fced --- cut ---- e3", "ClientId": "4900 --- cut ---- 93d98" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
Blazor客户端配置
修改AddTask方法调用目标API:
protected async Task AddTask() { try { // 此处抛出未授权错误 var result = await _downstreamApi.GetForUserAsync<string>( "ToDoList", options => { options.RelativePath = "api/mytodo"; options.BaseUrl = "https://localhost:44351/"; }); } catch(Exception ex) { var exe = ex; } // 原API调用正常 await _downstreamApi.PostForUserAsync("TodoList", toDo); Navigation.NavigateTo("todolist"); }
核心原因
通过endpoints.Map创建的极简端点,默认不会自动验证JWT令牌的受众(Audience);而控制器API因AddMicrosoftIdentityWebApi的内置配置会自动处理受众校验。当DownstreamApi获取的令牌受众与API的ClientId不匹配时,就会返回401未授权。
解决步骤
为API配置明确指定受众
在API的appsettings.json的AzureAd节点添加Audience字段,值为API自身的ClientId:"AzureAd": { "Instance": "https://login.microsoftonline.com/", "Domain": " --- cut ---- .onmicrosoft.com", "TenantId": "fced --- cut ---- e3", "ClientId": "4900 --- cut ---- 93d98", "Audience": "4900 --- cut ---- 93d98" }为极简端点配置JWT验证规则
在API的Startup.cs的ConfigureServices中,显式配置JWTBearer的令牌验证参数,确保受众匹配:services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(Configuration, options => { options.TokenValidationParameters.ValidAudience = Configuration["AzureAd:ClientId"]; });或者在映射端点时,直接指定使用JWT授权策略:
app.UseEndpoints(endpoints => { endpoints.Map("/api/mytodo", (context) => context.Response.WriteAsync("success")) .RequireAuthorization(JwtBearerDefaults.AuthenticationScheme); });验证DownstreamApi的令牌范围
检查Blazor端appsettings.json中DownstreamApis:ToDoList:Scopes配置,确保包含API的正确范围(格式通常为api://{API-ClientId}/.default)。
内容的提问来源于stack exchange,提问作者ari

