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

ASP.NET Core 5 Azure AD JWT认证context.User.Claims为空问题

问题场景
  • 运行环境:ASP.NET Core 5 Web API,对接Azure服务,已在所属租户Azure AD中完成应用注册,授权相关业务逻辑编写在Authorization授权处理器中,目标是将JWT令牌内的声明提取到context.User.Claims。
  • 异常表现:手动使用JwtSecurityTokenHandler读取请求头context.Request.Headers["Authorization"]携带的JWT令牌时,可以正常解析得到全部声明,但context.User.Claims集合始终为空。
  • 异常令牌的核心字段取值:
[aud, https://graph.microsoft.com]
[iss, https://sts.windows.net/[tenant-id]/]
  • 现有JWT认证配置(位于Startup.ConfigureServices()方法中):
services.AddAuthentication(sharedOptions =>
{
    sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(option =>
{
    option.Audience = audience;
    option.Authority = authority; 
    option.TokenValidationParameters = new TokenValidationParameters
    {
        ClockSkew = TimeSpan.FromHours(1), 
        ValidateLifetime = true,
        ValidateIssuer = true,
        ValidIssuer = authority,
        ValidateAudience = true,
        ValidAudience = audience
    };
});
已尝试的排查操作
  • 直接将JWT中解析得到的iss、aud值填入authority和audience配置项
  • 测试v2端点配置组合:
    • authority(令牌颁发者):https://login.microsoftonline.com/[tenant-id]/v2.0
    • audience(令牌受众):app://[client-id]
  • 所有配置组合测试后,context.User.Claims仍为空,需要确认audience与authority参数的正确配置方式。
根因说明

context.User.Claims为空的核心原因是JWT Bearer认证中间件没有完成令牌校验通过,不会将声明注入到用户上下文中。你当前拿到的JWT是颁发给Microsoft Graph服务的访问令牌,不是颁发给你自定义API应用的令牌,无论怎么调整配置参数,中间件都会因为受众校验不通过拒绝认证,手动解析令牌不经过校验逻辑,所以能读到声明。

正确配置方案

1. 先修正令牌获取逻辑

访问令牌的aud(受众)字段必须匹配你自己注册的API应用,不能为https://graph.microsoft.com。客户端申请令牌时,scope参数需要填写你自己的API在应用注册时暴露的权限范围,格式通常为api://<你的API应用客户端ID>/.default或自定义作用域,不能填写Microsoft Graph的权限范围。

2. authority 参数配置

你当前拿到的令牌iss字段为https://sts.windows.net/[tenant-id]/,属于Azure AD v1端点颁发的令牌,对应的authority必须配置为完全一致的https://sts.windows.net/[替换为实际租户ID]/,不要混用v2.0端点地址。
如果后续切换到v2端点申请令牌,令牌iss会变为https://login.microsoftonline.com/[tenant-id]/v2.0,此时再将authority替换为对应v2地址即可,两个版本的端点和令牌不能交叉配置。

3. audience 参数配置

audience必须和最终拿到的、颁发给你自己API的令牌中aud字段完全一致:

  • 针对v1端点颁发的令牌,aud取值为你API应用注册时配置的应用ID URI,常规格式为api://<你的API应用客户端ID>
  • 禁止使用https://graph.microsoft.com作为audience取值,该值对应的受保护资源是Microsoft Graph,不是你的自定义API。

4. 修正后的完整配置

你原有配置重复在AddJwtBearer根级别和TokenValidationParameters中设置了同名字段,保留一套配置即可,避免取值冲突。可参考以下配置,同时开启认证失败日志方便后续排查:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ClockSkew = TimeSpan.FromHours(1),
            ValidateLifetime = true,
            ValidateIssuer = true,
            // 替换为实际租户ID,和令牌iss字段完全匹配
            ValidIssuer = "https://sts.windows.net/[替换为你的租户ID]/",
            ValidateAudience = true,
            // 替换为你自己API的应用ID URI,和令牌aud字段完全匹配
            ValidAudience = "api://[替换为你的API应用客户端ID]",
            // 如果存在多个允许的受众,可改用ValidAudiences传入数组
            // ValidAudiences = new[] { "api://[client-id]", "其他合法aud值" }
        };
        // 可选:注册认证失败事件,打印错误信息快速定位校验问题
        options.Events = new JwtBearerEvents
        {
            OnAuthenticationFailed = context =>
            {
                var failReason = context.Exception.Message;
                // 此处可添加日志逻辑记录失败原因
                return Task.CompletedTask;
            }
        };
    });

配置完成后,确保客户端携带的是颁发给你自身API的合法令牌,JWT Bearer中间件校验通过后会自动将令牌内的声明填充到context.User.Claims中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 23:24:25