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

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未授权。

解决步骤

  1. 为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"
    }
    
  2. 为极简端点配置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);
    });
    
  3. 验证DownstreamApi的令牌范围
    检查Blazor端appsettings.json中DownstreamApis:ToDoList:Scopes配置,确保包含API的正确范围(格式通常为api://{API-ClientId}/.default)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 10:17:06