Как передать информацию об ошибках IsActiveAsync пользователям и клиентам? - PullRequest
0 голосов
/ 01 сентября 2018

В моем проекте IdentityServer4 я реализую IProfileService. Метод IsActiveAsync вызывается несколько раз после успешной аутентификации пользователя-пользователя через веб-страницу входа в систему при использовании неявных и гибридных потоков.

Я заметил, что он вызывается, когда context.Caller является одним из следующих значений:

  • AuthorizeEndpoint (с претензиями пользователя)
  • AuthorizationCodeValidation (с претензиями пользователя)
  • AccessTokenValidation (без претензий пользователя)

Из-за ошибки мой кодовый набор context.IsActive = false - и когда это произошло, веб-браузер, который использовался для перехода на страницу входа, был просто перенаправлен обратно на страницу входа без сообщения об ошибке или информации о причине. Пользователи будут смущены, почему они успешно прошли аутентификацию, но предложат войти снова. Также не были добавлены новые параметры строки запроса.

В журналах IdentityServer4 отображается причина:

[23:16:40 Информация] IdentityServer4.ResponseHandling.AuthorizeInteractionResponseGenerator Отображение логина: пользователь не активен

Теперь предположим, что мой код IsActive = false не был ошибкой, а фактически был внутренним (потому что, например, учетная запись пользователя действительно была отключена в микросекундах между различными HTTP-запросами OAuth / OpenIDConnect), и в этом случае как я могу убедиться, что это сообщение представлено пользователю и / или клиентскому программному обеспечению?

1 Ответ

0 голосов
/ 01 сентября 2018

После некоторого расследования я решил обновить ответ.

Прежде всего, context.IsActive используется для указания того, следует ли выполнять GetProfileDataAsync.

Проблема заключается в том, что клиент запускает несколько вызовов в ProfileService для получения информации. Эти отдельные вызовы инициируются клиентом и выполняются после входа пользователя в систему.

Для прямого ответа вы можете добавить код в метод Login. Когда пользователь не активен, вы можете ответить сообщением об ошибке. Я думаю, что это лучшее место для проверки, потому что это предотвратит множество действий.

Следующий фрагмент взят из одного из образцов IdentityServer. Он обрабатывает запрос на вход.

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginInputModel model, string button)
{
    if (ModelState.IsValid)
    {
        var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberLogin, lockoutOnFailure: true);
        if (result.Succeeded)
        {
            var user = await _userManager.FindByNameAsync(model.Username);

            // Assume user has property IsActive for this example.
            // You can implement this anyway you like.
            if (user.IsActive)
            {
                ...
            }
        }

        ModelState.AddModelError("", AccountOptions.InvalidCredentialsErrorMessage);
    }

    // something went wrong, show form with error
    var vm = await BuildLoginViewModelAsync(model);
    return View(vm);
}

Вы можете добавить любое понравившееся вам сообщение, используя ModelState.AddModelError.

Теперь предположим, что пользователь вошел в систему и позже был деактивирован, тогда ProfileService не будет возвращать претензии. Вместо этого это приведет к 401: пользователь не активен.

Затем клиент выдаст исключение, потому что запрос должен быть успешным: HttpResponseMessage.EnsureSuccessStatusCode.

К счастью, есть опция для обработки исключения. И это для реализации событий OIDC. Это простой пример:

services.AddOpenIdConnect("oidc", "Open Id connect", options =>
{
    options.Events = new OpenIdConnectEvents()
    {
        // When a user is not active this will result in a 401
        OnAuthenticationFailed = (context) =>
        {
            // Clear the exception, otherwise it is re-thrown after this event.
            context.HandleResponse();
            // Handle the exception, e.g. redirect to an error page.
            context.Response.Redirect($"LoginError/?message={context.Exception.Message}");

            return Task.FromResult(0);
        },
    }
}

Это может быть то, что вы ищете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...