ASP.NET 核心 3.1:User.Identity.Name 在 API 控制器中为空,但声明名称存在

ASP.NET Core 3.1: User.Identity.Name is empty in API Controller, but claim name is present

我正在将 Identity Server 添加到我现有的项目中。基本上我已经准备好了一切,但是当我向 API 发出请求时,User.Identity.Name 为空。但是 User.Identity.Claims 包含名称声明:

我知道通过HttpContext.User.FindFirstValue(ClaimTypes.Name)获取用户名的方式,但需要大量代码重构,所以我宁愿避免这种方式。

我按照以下方式在身份服务器中配置了 ApiResources:

public static IEnumerable<ApiResource> ApiResources => new[]
{
    new ApiResource
    {
        Name = "my-api",
        DisplayName = "My API",
        Description = "My API",
        Scopes = new List<string> { "my-api"},
        UserClaims = new List<string> {
            JwtClaimTypes.Email,
            JwtClaimTypes.Name,
            JwtClaimTypes.Subject,
            JwtClaimTypes.Role,
        }
    }
};

和客户:

public static IEnumerable<Client> Clients =>
    new List<Client>
    {
        new Client
        {
            // ...
            AllowedScopes =
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.Email,
                "name",
                "roles",
                "my-api",
            }
        }
    };

API 项目中的身份验证设置:

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
    options.Authority = config["IdentityServer:Domain"];

    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidIssuer = config["IdentityServer:Domain"],
        ValidateAudience = false
    };
});

services.AddAuthorization(options =>
{
    options.AddPolicy("ApiScope", policy =>
    {
        policy.RequireAuthenticatedUser();
        policy.RequireClaim("scope", "my-api");
    });
});

请指教我做错了什么?

问题是微软和 OpenID connect 对于“名称”声明的名称应该是什么有不同的看法。所以你需要做的是告诉系统名称声明的名称是什么,通过:

    .AddJwtBearer(opt =>
    {
        ...      
        opt.TokenValidationParameters.RoleClaimType = "roles";
        opt.TokenValidationParameters.NameClaimType = "name";
        ...
    }