IdentityServer4 Все клиентские области в токене
У меня есть приложение для нескольких арендаторов, защищенное реализацией IdentityServer4. Я недавно обновил его до последней версии ID4, и поведение, похоже, изменилось. Ранее я мог сделать запрос с TokenClient внутри пакета IdentityModel:
var parameters = new Dictionary<string, string>();
parameters.Add("username", loginModel.UserName);
parameters.Add("password", loginModel.Password);
var tokenClient = new TokenClient(new Uri(new Uri(accountsConfig.EndpointUrl), "/connect/token").ToString(), accountsConfig.ClientId, accountsConfig.Secret, null, AuthenticationStyle.PostValues);
var tokenResponse = await tokenClient.RequestCustomGrantAsync("AgentLogin", extra: parameters);
Он вернул бы все области, определенные для клиента в токене. Это уже не так. Как мне настроить ID4, чтобы сделать это без явного запроса их внутри TokenClient?
public class AgentLoginCustomGrantValidator : IExtensionGrantValidator
{
private readonly ILogger<AgentLoginCustomGrantValidator> _logger;
private readonly IAdminUserService _adminUserService;
public AgentLoginCustomGrantValidator(ILogger<AgentLoginCustomGrantValidator> logger, IAdminUserService adminUserService)
{
_logger = logger;
_adminUserService = adminUserService;
}
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
try
{
var username = context.Request.Raw.Get("username");
var password = context.Request.Raw.Get("password");
var userId = _adminUserService.AuthenticateUser(username, password);
if (userId != null)
{
var agencyUser = _adminUserService.GetUser(userId.Value);
context.Result = new GrantValidationResult($"{userId}", GrantType, agencyUser.Roles.Select(x => new Claim(JwtClaimTypes.Role, x.Name)).Concat(new List<Claim>() { new Claim(JwtClaimTypes.Name, agencyUser.UserName) { } }));
}
else
{
_logger.LogWarning($"Bum creds: {username} ");
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidClient, "Invalid credentials");
}
}
catch (Exception ex)
{
_logger.LogError(ex.ToString());
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidClient, ex.Message);
}
}
public string GrantType => "AgentLogin";
}
1 ответ
Похоже, Identity Server 4 по умолчанию возвращает только запрошенные ресурсы удостоверений или API для каждого клиента. Однако это поведение можно легко переопределить, чтобы вернуть все области независимо от того, были ли они запрошены в запросе токена или нет. Вы можете создать CustomClaimsService
который наследует от DefaultClaimsService
,
public class CustomClaimsService : DefaultClaimsService
{
public CustomClaimsService(IProfileService profile, ILogger<DefaultClaimsService> logger) : base(profile, logger)
{
}
public override async Task<IEnumerable<Claim>> GetAccessTokenClaimsAsync(ClaimsPrincipal subject,
Resources resources, ValidatedRequest request)
{
var baseResult = await base.GetAccessTokenClaimsAsync(subject, resources, request);
var outputClaims = baseResult.ToList();
//If there are any allowed scope claims that are not yet in the output claims - add them
foreach (var allowedClientScope in request.Client.AllowedScopes)
{
if (!outputClaims.Any(x => x.Type == JwtClaimTypes.Scope && x.Value == allowedClientScope))
{
outputClaims.Add(new Claim(JwtClaimTypes.Scope, allowedClientScope));
}
}
return outputClaims;
}
}
Затем просто зарегистрируйте его в IdentityServerBuilder
сервисный контейнер.
var builder = services.AddIdentityServer(options =>
{
//Your identity server options
});
//Register the custom claims service with the service container
builder.Services.AddTransient<IClaimsService, CustomClaimsService>();
Каждый токен доступа теперь будет содержать все области, которые разрешены данному клиенту.