Получение JWT токена с включенной 2fa

176
19 декабря 2018, 18:30

Господа, пытаюсь сделать получение JWT токена на аккаунте с включенным Two-factor authentication (2fa). Как я это сделал:

  1. Отправляем POST запрос с JSON телом, которое содержит логин и пароль.
  2. Вызываем signInManager.PasswordSignInAsync, который выдает нам SignInResult.
  3. Проверяем SignInResult:
    • если это Succeeded - генерируем токен.
    • если это RequiresTwoFactor - проверяем наличие ключа в запросе, если он есть - пробуем авторизоваться, нет - ошибка.
  4. Выводим токен.

Действия при RequiresTwoFactor:

  1. Выполняем signInManager.GetTwoFactorAuthenticationUserAsync();
  2. Далее выполняем signInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, false, false), который также дает нам статус.
  3. Если Succeeded, то генерируем токен и отдаем.

Сам код пока имеет такой набросок:

[HttpPost("[action]/{key?}")]
public async Task<ActionResult> Auth([FromBody] TokenRequest tokenRequest, string key)
{
    if (tokenRequest == null)
        return StatusCode(400, "Request cannot be null!");
    var username = tokenRequest.UserName;
    var password = tokenRequest.Password;
    var result = await signInManager.PasswordSignInAsync(username, password, false, lockoutOnFailure: true);
    if (result.Succeeded)
    {
        var user = await userManager.FindByNameAsync(username);
        if (user != null)
        {
            var principal = await signInManager.CreateUserPrincipalAsync(user);
            var token = GenerateToken(principal);
            var response = new
            {
                token,
                principal.Identity.Name
            };
            return Json(response);
        }
    }
    if (result.IsLockedOut)
    {
        return StatusCode(423, "Account locked out!");
    }
    if (result.RequiresTwoFactor)
    {
        if (key == null)
            return StatusCode(400, "Two-factor authentication `key` needed!");
        var user = await signInManager.GetTwoFactorAuthenticationUserAsync();
        if (user == null)
            return StatusCode(502, "Unable to load two-factor authentication user.");
        var authenticatorCode = key.Replace(" ", string.Empty).Replace("-", string.Empty);
        var authResult = await signInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, false, false);
        if (authResult.Succeeded)
        {
            var principal = await signInManager.CreateUserPrincipalAsync(user);
            var token = GenerateToken(principal);
            var response = new
            {
                token,
                principal.Identity.Name
            };
            return Json(response);
        }
        else if (authResult.IsLockedOut)
        {
            return StatusCode(423, "Account locked out!");
        }
        else
        {
            return StatusCode(400, "Invalid authenticator code.");
        }
    }
    return StatusCode(400, "Login Failed!");
}

Все это вроде как работает, но вот одна загвоздка - тут используются Cookie, а точнее:

  • В момент первой авторизации нам вешает куку Identity.TwoFactorUserId с неким ключом и дает сообщение "Требуется 2fa код".
  • Далее как я понял, мы через signInManager.GetTwoFactorAuthenticationUserAsync(); эту куку считываем, а также код присланный вторым запросом и сверяем все это.

Вопрос:
Как мне грамотно реализовать авторизацию с 2fa, не используя куки, ведь в API не очень хорошо (да и не очень удобно) использовать куки, или ошибаюсь?

За основу взял этот ответ.

Для чего это:

Делаю сайт на ASP.Net Core 2.1, который будет неким центральным хабом (аккаунт с возможностью управления, магазин, взаимодействие с игровым миром (сервер будет выдавать свое API для этого, сайт здесь будет в роли клиента).

Для этого всего требуется еще реализовать клиентское приложение, которое сейчас разрабатывается на WPF (его задачи: информация об аккаунте, балансе пользователя, информация о персонажах, обновление клиента и др. информация). По сути это клиентское приложение, которое будет выводить информацию, с минимальным набором "изменяемых" API (то есть не будет пополнение счета через него, не будет изменение пароля и др.). Вот в нем требуется узнать пользователя, авторизовать его, получить его информацию и в дальнейшем пустить в игру.

Answer 1

У меня была подобная проблема и решил её следующим способом:

var authenticatorCode = 
    model.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty);
var is2faTokenValid = await _userManager.VerifyTwoFactorTokenAsync(
    user, _userManager.Options.Tokens.AuthenticatorTokenProvider, authenticatorCode
);
READ ALSO
Объект не удаляется Unity3d 2d

Объект не удаляется Unity3d 2d

Я хочу чтобы при столкновении один Объект удалялся

125
xamarin компоновка элементов

xamarin компоновка элементов

Пытаюсь освоить xamarin как было бы грамотнее реализовать расположение компонентов на activity так как на картинкепримечание компоненты генерируются...

170
Клик на SubMenuItem в контекстном меню

Клик на SubMenuItem в контекстном меню

У меня есть дата грид и в ресурсах к ней определено контекстное менюОно статичное, но мне нужно динамично добавлять sub MenuItem для одного из айтемов...

153