Как повторно авторизовать пользователя с помощью аутентификации IdentityServer4

#angular #asp.net-core #identityserver4 #abp

#angular #asp.net-core #identityserver4 #abp

Вопрос:

У нас есть решение, основанное на стороннем фреймворке ABP и его многоуровневой архитектуре: Взаимодействие слоев

Мы используем Angular в качестве веб-интерфейса и IdentityServer4 для аутентификации пользователя. Итак, мы запускаем 2 хоста — хост HTTP API и хост IdentityServer, а что касается web face — он работает стандартным образом: поле входа, пользователь вводит учетные данные — вуаля.

Тем не менее, у нас есть пользовательская настройка, позволяющая использовать одно и то же имя для входа под другим клиентом. Список клиентов отображается в виде выпадающего списка в пользовательском интерфейсе, и мы хотели бы повторно авторизовать пользователя с выбранным клиентом вместо пользователя, вошедшего в систему в данный момент. Это должно выглядеть как простая перезагрузка страницы. Проблема в том, что у меня нет четкого понимания, как это реализовать. Я пытался использовать следующий вызов с уровня приложения, но он не работает (ошибка «Обработчик аутентификации не зарегистрирован для идентификатора scheme «.Приложение ‘…», но я не знаю, как настроить конфигурацию аутентификации на прикладном уровне, чтобы иметь возможность работать с нашим IdentityServer):

     [HttpGet]
    public async Task<TenantDto> SwitchTenantForCurrentUser(Guid? tenantId)
    {
        var abxUser = await _abxUserRepository.FirstOrDefaultAsync(x => x.Login == CurrentUser.UserName amp;amp; x.Tenant.AbpId == tenantId);

        if (abxUser == null)
            return null;

        using var _ = _abpCurrentTenant.Change(tenantId);

        var currentTenant = await _abxTenantRepository.FirstOrDefaultAsync(x => x.AbpId == _abpCurrentTenant.Id.Value);
        var identityUser = await _identityUserRepository.FindByNormalizedUserNameAsync(abxUser.Login.ToUpper());

        if (await _signInManager.CanSignInAsync(identityUser))
        {
            await _signInManager.SignOutAsync();
            await _signInManager.SignInAsync(identityUser, true);
        }

        return ObjectMapper.Map<Tenant, TenantDto>(currentTenant); // Not decided yet what to return, it depends on proper implementation
    }
  

Часть конфигурации хоста Http API относительно аутентификации:

     private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
    {
        context.Services.AddAuthentication("Bearer")
            .AddIdentityServerAuthentication(options =>
            {
                options.Authority = configuration["AuthServer:Authority"];
                options.RequireHttpsMetadata = true;
                options.ApiName = "CentralTools";
                options.JwtBackChannelHandler = new HttpClientHandler
                {
                    //TODO: use valid certificate in future and change the logic
                    ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
                };
            });

        context.Services.AddAbpIdentity().AddDefaultTokenProviders();
  

Ответ №1:

Миссия выполнена. Шаги:

  1. СЕРВЕРНАЯ часть: внедрите и зарегистрируйте пользовательский валидатор типа гранта в проекте IdentityServer:

    SwitchToTenantGrantValidator: IdentityServer4.Проверка.IExtensionGrantValidator

Короче говоря, ValidateAsync принимает данные аутентифицированного пользователя (его токен доступа, идентификатор клиента и т.д.) И принимает решение, должен ли пользователь быть допущен. Метод записывает данные целевого клиента в объект context resu<

  1. ИНТЕРФЕЙС: выполните вызов IdentityServer с заданным типом пользовательского разрешения, предоставив данные, необходимые для (1). Мы использовали Angular, поэтому мне пришлось расширить OAuthService для поддержки пользовательского запроса типа grant;

  2. Приведите все в порядок (если (2) прошло успешно), чтобы отобразить правильные данные в пользовательском интерфейсе: очистите старые состояния и т.д.