0

我正在使用IdentityModel.AspNetCore.AddClientAccessTokenHandler()扩展来自HttpClient动向 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 标头中,则会到达我的端点并返回预期的响应。如果我使用.AddClientAccessTokenHandler(),我会得到 403 - Forbidden。我错过了什么?

4

1 回答 1

2

由于您在 name 下注册客户端auth,因此您也应该这样检索它。

这基本上意味着我希望你使用这样的东西,或者它是等价的:

_httpClient = factory.CreateClient("auth");

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

附言。我在手机上;目前还不能很好地访问我的资源。

于 2020-07-13T12:05:12.823 回答