IdentityServer4 Все клиентские области в токене - PullRequest
0 голосов
/ 02 января 2019

У меня есть приложение для нескольких арендаторов, защищенное реализацией 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 Ответ

0 голосов
/ 03 января 2019

Похоже, 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>();

Каждый токен доступа теперь будет содержать все области, которые разрешен данному клиенту.

...