将 HttpClient 与 .AddClientAccessTokenHandler() 扩展一起使用时,不包括角色声明

When using HttpClient with .AddClientAccessTokenHandler() extension, role claim is not included

我正在使用 IdentityModel.AspNetCore.AddClientAccessTokenHandler() 扩展自动向 API.一些 API 端点是根据角色授权的。但由于某种原因,添加到请求的访问令牌不包含角色声明。如果我不使用 .AddClientAccessTokenHandler() 并手动检索令牌并使用 SetBearerToken(accessTone) 设置它,那么我可以到达我的角色授权端点。

我的启动是:

services.AddAccessTokenManagement(options =>
{
    options.Client.Clients.Add("auth", new ClientCredentialsTokenRequest
    {
        Address = "https://localhost:44358/connect/token", 
        ClientId = "clientId",
        ClientSecret = "clientSecret",
    });
});

WebApi 调用:

var response = await _httpClient.GetAsync("api/WeatherForecast/SecretRole");

身份服务器配置:

public static IEnumerable<ApiResource> GetApis() =>
    new List<ApiResource>
    {
        new ApiResource("WebApi", new string[] { "role" })
            { Scopes = { "WebApi.All" }}
    };

public static IEnumerable<ApiScope> GetApiScopes() =>
    new List<ApiScope>
        { new ApiScope("WebApi.All") };

public static IEnumerable<IdentityResource> GetIdentityResources() =>
    new List<IdentityResource>
    {
        new IdentityResources.OpenId(),
        new IdentityResources.Profile(),
        new IdentityResource 
        {
            Name = "roles",
            UserClaims = { "role" }
        }
    };

public static IEnumerable<Client> GetClients() =>
    new List<Client>
    {
        new Client
        {
            ClientId = "clientId",
            ClientSecrets = { new Secret("clientSecret".ToSha256()) },
            AllowedGrantTypes = 
            { 
                GrantType.AuthorizationCode, 
                GrantType.ClientCredentials
            },
            AllowedScopes =
            {
                "WebApi.All",                        
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                "roles"
            },
            RedirectUris = { "https://localhost:44305/signin-oidc" },
            PostLogoutRedirectUris  = { "https://localhost:44305/Home/Index" },
            AlwaysIncludeUserClaimsInIdToken = false,
            AllowOfflineAccess = true,
        }
    };

出于测试目的,我从 Program.cs

手动添加用户
public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();
    using (var scope = host.Services.CreateScope())
    {
        var userManager = scope.ServiceProvider.GetRequiredService<UserManager<IdentityUser>>();
        AddUsers(userManager).GetAwaiter().GetResult();
    }
    host.Run();
}

private static async Task AddUsers(UserManager<IdentityUser> userManager)
{
    var adminClaim = new Claim("role", "Admin");
    var visitorClaim = new Claim("role", "Visitor");

    var user = new IdentityUser("Admin");
    await userManager.CreateAsync(user, user.UserName);
    await userManager.AddClaimAsync(user, adminClaim);

    user = new IdentityUser("Visitor");
    await userManager.CreateAsync(user, user.UserName);
    await userManager.AddClaimAsync(user, visitorClaim);
}

因此,如果我使用手动访问令牌检索并将其自己添加到 HttpClient headers,那么我的端点已到达并且 returns 预期响应。如果我使用 .AddClientAccessTokenHandler(),我会收到 403 - Forbidden。我错过了什么?

由于您是以 auth 的名称注册客户端,因此您也应该这样检索它。

这基本上意味着我希望您使用类似这样的东西,或者等效的东西:

_httpClient = factory.CreateClient("auth");

基本上,此机制可确保您能够为各种 API 和设置检索 HttpClients

ps。我在移动;目前对我的资源的访问不是很好。