Identity Server 4 Олицетворение пользователя - PullRequest
0 голосов
/ 02 декабря 2018

Я пытаюсь реализовать функцию олицетворения в службе Identity Server 4.Я понимаю, что есть много людей, которые против реализации этого, как я хочу, но мне действительно нужно полное перенаправление обратно на сервер SSO, чтобы сгенерировать новый список утверждений.У пользователя, который олицетворяет себя, будет совершенно другой набор правил, связанных с ними в качестве утверждений, поэтому он должен исходить из IdSrvr.

Я прочитал https://github.com/IdentityServer/IdentityServer4/issues/853,, а также IdentityServer4- Как реализовать олицетворение

Вот что я пытался сделать до сих пор. Мы прекрасно сделали это в Identity Server 3 со значениями ACR и предварительной авторизацией даже на UserService.

Этот метод контроллера, который я вызываю с одного из Клиентов моего сервера идентификации:

public IActionResult Impersonate(string userIdToImpersonate, string redirectUri)
{
        return new ChallengeResult(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties(){RedirectUri = redirectUri, Items = { {"acr_values", $"userIdToImpersonate:{userIdToImpersonate}"}}});            
}

Вот мой OnRedirectToProvider:

OnRedirectToIdentityProvider = context =>
{
    if (context.Properties.Items.ContainsKey("acr_values"))
    {
       context.ProtocolMessage.AcrValues = context.Properties.Items["acr_values"].ToString();
    }

    return Task.CompletedTask;
}

Это где я начинаю заблудиться, вна данный момент я унаследовал от класса AuthorizeInteractionResponseGenerator и реализовал свой собственный с переопределением для ProcessLoginAsync (это единственное, что я мог найти, что было близко к событию перед аутентификацией ранее)

    protected override async Task<InteractionResponse> ProcessLoginAsync(ValidatedAuthorizeRequest request)
    {
        if (!request.IsOpenIdRequest) return await base.ProcessLoginAsync(request);
        var items = request.GetAcrValues();
        if (items.Any(i => i.Contains("userIdToImpersonate")) && request.Subject.IsAuthenticated())
        {
            //handle impersonation
            var userIdToImpersonate = items.FirstOrDefault(m => m.Contains("userIdToImpersonate")).Split(':').LastOrDefault();
            request.Subject = await _signInManager.ImpersonateAsync(userIdToImpersonate);




            //var userToImpersonate = await _signInManager.UserManager.FindByIdAsync(userIdToImpersonate);
            //if (userToImpersonate == null) return await base.ProcessLoginAsync(request);

            //var userBeingImpersonated = await _signInManager.UserManager.FindByIdAsync(userIdToImpersonate);

            //var currentUserIdentity = await _signInManager.CreateUserPrincipalAsync(userBeingImpersonated);
            //var currentClaims = currentUserIdentity.Claims.ToList();
            //currentClaims.Add(new Claim(IdentityServiceClaimTypes.ImpersonatedById, request.Subject.IsBeingImpersonated() ? request.Subject.GetClaimValue(IdentityServiceClaimTypes.ImpersonatedById) : _signInManager.UserManager.GetUserId(request.Subject)));
            //request.Subject = new ClaimsPrincipal(new ClaimsIdentity(currentClaims));

            //return await base.ProcessLoginAsync(request);



            return new InteractionResponse();
        }
        else
        {
            return await base.ProcessLoginAsync(request);
        }
    }

Как видите, я попробовал несколько разных вещей здесь: когда я не использую OIDC в ​​качестве схемы аутентификации, а мой IdServer / Site - это тот же сайт, у меня была функцияИон, с которым работало подражание.Вот где _signInManager.ImpersonateAsync (...).Вот эта реализация:

    public async Task<ClaimsPrincipal> ImpersonateAsync(string userIdToImpersonate)
    {
        var userBeingImpersonated = await UserManager.FindByIdAsync(userIdToImpersonate);
        if (userBeingImpersonated == null) return null;

        var currentUserIdentity = await CreateUserPrincipalAsync(userBeingImpersonated);
        var currentClaims = currentUserIdentity.Claims.ToList();
        currentClaims.Add(new Claim(IdentityServiceClaimTypes.ImpersonatedById, Context.User.IsBeingImpersonated() ? Context.User.GetClaimValue(IdentityServiceClaimTypes.ImpersonatedById) : UserManager.GetUserId(Context.User)));
        //sign out current user
        await SignOutAsync();

        //sign in new one
        var newIdentity = new ClaimsPrincipal(new ClaimsIdentity(currentClaims));
        await Context.SignInAsync(IdentityConstants.ApplicationScheme, newIdentity);
        return Context.User;
    }

Стремясь просто «заменить» того, кто входил в систему, или, по крайней мере, тот, кто думал, что сервер идентификации делал вход, я просто заменил Request.Subject на результат олицетворения.,На самом деле это ничего не меняет, что я могу найти, по крайней мере, в моем клиентском приложении.Если я использую URI перенаправления 'https://localhost:44322/signin-oidc' (localhost, потому что я запускаю сайты локально), я получаю сообщение "Ошибка корреляции при перенаправлении signin-oidc".Если кто-то реализовал что-то подобное или сделал что-то подобное, я был бы очень признателен за помощь в получении этого завершения.

Предложения приветствуются для совершенно разных реализаций, это был мой лучший пример того, что безупречно работало с idsrvr3.

...