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

Azure AD实现SSO后React调用.NET Core Web API报401未授权

401 Unauthorized 排查方案

按以下优先级逐一排查,覆盖绝大多数配置错误场景:

1. 修正中间件顺序(最高频错误)

你当前Startup.cs的中间件顺序完全错误,CORS中间件放在了UseEndpoints之后,不会对请求生效,跨域预检请求(OPTIONS)会直接被认证中间件拦截返回401。
将Configure方法里的中间件调整为以下正确顺序:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseRouting();
    // 跨域配置必须放在Routing之后,认证、授权、端点映射之前
    app.UseCors(x => x
         .AllowAnyOrigin()
         .AllowAnyMethod()
         .AllowAnyHeader());
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });

    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "TMS v1");
    });
}

原配置中空参数的WithHeaders()、WithExposedHeaders()无实际作用,直接删除即可。

2. 确认调用API使用了正确的访问令牌

你前端loginRequest里申请的User.Read是微软Graph API的权限,绝对不能拿Graph的令牌调用自己的Web API:Azure AD按资源维度签发令牌,Graph令牌的受众(aud声明)是https://graph.microsoft.com,你的API会直接拒绝该令牌。
调用自有API前,必须调用MSAL实例的acquireTokenSilent方法,传入apiConfig.scopes单独申请对应自有API的访问令牌,再将该令牌以Authorization: Bearer <token>的格式放到请求头中。
拿到令牌后先解析令牌内容,核对以下核心声明:

  • aud(受众):必须和服务端配置的合法受众完全匹配,要么是服务端Azure应用的ClientId(guid格式),要么是你配置的应用ID URI(api://xxx格式)
  • scp(委托权限):必须包含你配置的User.Read权限
  • iss(签发者):格式必须为https://sts.windows.net/<你的租户ID>/,和服务端配置的TenantId一致
  • 开启角色校验的场景下,roles声明必须包含Admin值

3. 修复服务端受众配置不匹配问题

你当前服务端AzureAd配置仅填写了ClientId(guid格式),但你暴露的API使用api://<app-id>/User.Read格式的应用ID URI。默认情况下AddMicrosoftIdentityWebApi仅将ClientId作为合法受众,如果令牌的aud是api://开头的URI,会直接因受众校验失败返回401。
在AzureAd配置节点中补充Audience项:

"AzureAd": {
  "Instance": "https://login.microsoftonline.com/",
  "Domain": "example.onmicrosoft.com",
  "ClientId": "392xxxx2-bxx4-4xxf-axxc-505bd9c6d8b4",
  "TenantId": "06xxx2xbe-9xxe-4xx8-bxxd-e1a6ebxxxxd",
  "scopes": "api://3xxxxe52-bxx4-4xxf-axx2c-505bxxxxb4/User.Read",
  "Audience": "api://3xxxxe52-bxx4-4xxf-axx2c-505bxxxxb4"
}

注意:你贴出的配置中,服务端ClientId、scopes里的应用ID、前端apiConfig里的scope应用ID三个值打码后长度不一致,大概率是复制时粘贴错误,必须确保这几个值和Azure门户中服务端应用的实际配置完全一致,单个字符错误都会导致校验失败。同时核对Azure门户「公开API」页面的应用程序ID URI,必须和scope前缀完全匹配。

4. 缩小问题定位范围

临时注释Controller上的[RequiredScope]特性、Action上的[Authorize(Roles ="Admin")]特性,添加一个无授权要求的测试接口,根据返回结果定位问题:

  • 去掉授权特性后仍返回401:问题出在CORS配置、令牌受众不匹配、令牌签发者不合法、前端使用了错误资源的令牌这几个环节
  • 去掉特性后可正常访问,加回[RequiredScope]就返回401:说明令牌中无对应scp声明,需检查:Azure门户中是否给前端客户端授予了服务端API的委托权限(不是应用权限,SPA无法使用应用权限)、是否完成了管理员同意、前端申请令牌时传入的scope是否正确
  • 加回scope校验可正常访问,加回Roles校验返回401/403:说明令牌中无对应roles声明,需在服务端Azure应用中配置App Role,并给对应用户/用户组分配Admin角色。

用户权限配置位置说明

用户的访问权限(角色、权限范围)必须配置在服务端对应的Azure AD应用注册中:

  • 客户端应用仅需配置「可访问的服务端API及对应委托权限」,也就是在客户端应用的「API权限」页面添加服务端暴露的scope即可,不需要在客户端侧配置任何用户角色/权限规则
  • 服务端应用负责定义权限范围(Scope)、应用角色(App Role),用户/用户组的角色分配、权限校验逻辑全部在服务端侧完成,令牌中的scp、roles声明均由Azure AD根据服务端应用的配置签发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 03:30:59