Я использую расширения 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 - Запрещено. Что мне не хватает?