Как мы в Тинькофф использовали Windows Hello для аутентификации пользователя

в 15:49, , рубрики: .net, C#, uwp, windows hello, Блог компании Tinkoff.ru, разработка под windows
Windows Hello

Windows Hello – это технология биометрической аутентификации пользователя по отпечатку пальца, сетчатки глаза, трёхмерному сканированию лица и даже по венозной схеме ладони.

В сфере оказания финансовых услуг, важна безошибочная и безопасная аутентификация пользователя. Для авторизации мы используем двухфакторную систему из связки логина и пароля или номера телефона и пароля с подтверждением по коду, отправленному на привязанный номер мобильного телефона. Для дальнейшего упрощения доступа в авторизованную зону используется 4х значный ПИН-код.

После авторизации и создания ПИН-кода, аутентификацию пользователя можно переложить на плечи Windows Hello. Общая последовательность необходимых действий выглядит следующим образом:

  • Проверить возможность использования Windows Hello.
  • Проверка пользователя с помощью Windows Hello, что позволяет связать авторизованного Windows пользователя с нашим клиентом.
  • Кэширование созданного ранее ПИН-кода по идентификатору пользователя в защищённой области.
  • При последующих запусках приложения с авторизованным пользователем, автоматически запускается процедура аутентификации пользователя посредством Windows Hello. В случае успешной аутентификации из защищённой области запрашивается кэшированный ПИН-код.

Давайте рассмотрим каждый шаг подробнее на примерах кода.

Минимальным условием использования Windows Hello служит настроенный ПИН код доступа для входа в систему. В случае отсутствия у пользователя сертифицированного оборудования для биометрической аутентификации, будет использован ПИН код.

Мы это делаем так:

public async Task<WindowsHelloStatus> CheckHelloStatusAsync()
{
  var checkAvailabilityAsyncOperation = UserConsentVerifier.CheckAvailabilityAsync();
  var checkAvailabilityTask = checkAvailabilityAsyncOperation.AsTask();
  var completedTask = await Task.WhenAny(checkAvailabilityTask, Task.Delay(TimeSpan.FromSeconds(1)));
 
  if(completedTask == checkAvailabilityTask)
  {
    var availability = checkAvailabilityTask.Result;
 
    switch (availability)
    {
      case UserConsentVerifierAvailability.Available:
        return WindowsHelloStatus.Available;
      case UserConsentVerifierAvailability.DeviceBusy:
        return WindowsHelloStatus.Busy;
      case UserConsentVerifierAvailability.DisabledByPolicy:
        return WindowsHelloStatus.DisabledByPolicy;
      case UserConsentVerifierAvailability.NotConfiguredForUser:
        return WindowsHelloStatus.NotConfiguredForUser;
      default:
        return WindowsHelloStatus.Unavailable;
    }
  }
 
  checkAvailabilityAsyncOperation.Cancel();
  return WindowsHelloStatus.Unavailable;
}

Данный код не должен вызвать вопросов, здесь проверяется статус службы Windows Hello. UserConsentVerifierAvailability содержит чуть больше вариантов статуса службы, но для наших целей будет достаточно перечисленных в примере выше.

После установки пин-кода Тинькофф и успешной проверки доступности Windows Hello мы предлагаем пользователю подключить эту службу:

Как мы в Тинькофф использовали Windows Hello для аутентификации пользователя - 2

Если пользователь соглашается, то необходимо его аутентифицировать, для этого мы используем следующий код:

public async Task<bool> VerifyUserAsync()
{
  if (await CheckHelloStatusAsync() != WindowsHelloStatus.Available)
    return false;
 
  var result = await UserConsentVerifier.RequestVerificationAsync(requestMessage);
  return result == UserConsentVerificationResult.Verified;
}

В этом примере мы проверяем, что пользователь, использующий в данный момент устройство, тот же человек, что и владелец учётной записи. Как это сделать: UserConsentVerifier.RequestVerificationAsync – это метод, который берёт на себя проверку пользователя с помощью доступного варианта проверки, будь то аутентификация по отпечатку пальца, сетчатке глаза или любой другой способ. Удобство в том, что нам не приходится заботиться с помощью чего и как это происходит, главное, что такой вариант удовлетворяет нашим требованиям безопасности.

Без использования службы Windows Hello мы запрашиваем ввод пин-кода при каждом запуске приложения и долгом бездействии пользователя. Этот код используется для верификации запросов во время работы пользователя с приложением. В случае использования Windows Hello пользователю не нужно вводить этот код каждый раз и встаёт вопрос о безопасном хранении этого кода. Для этого на помощь приходит сервис PasswordVault, он позволяет хранить данные, требующие особого внимания к безопасности. Этот сервис не хранит данные в открытом виде. На устройствах, оборудованных специальным чипом для шифрования, сервис использует этот чип для защиты, на устройствах без чипа шифрования защита достигается программными средствами.

/// <summary>
/// Добавление данных пользователя для запросов к серверу
/// </summary>
/// <param name="userId">Идентификатор пользователя</param>
/// <param name="hash">ПИН-код доступа</param>
public void AddCredentials(string userId, string pin)
{
  var vault = new PasswordVault();
  vault.Add(new PasswordCredential(«Идентификатор Вашего приложения», userId, pin));
}

Этот пример показывает, как легко добавить данные в PasswordVault для хранения:

В случае смены или выхода пользователя в приложении необходимо выполнить удаление данных пользователя из хранилища паролей:

public void RemoveCredentials(string userId)
{
  var vault = new PasswordVault();
 
  var credentials = vault.Retrieve(«Идентификатор Вашего приложения», userId);
  if (credentials != null)
    vault.Remove(credentials);
}

В следующем примере представлен метод, который мы используем после запуска приложения:

public async Task<string> SignInAsync(string userId)
{
  if (await CheckHelloStatusAsync() != WindowsHelloStatus.Available)
    return null;
 
  var result = await UserConsentVerifier.RequestVerificationAsync(requestMessage);
  if (result != UserConsentVerificationResult.Verified)
    return null;
 
  var vault = new PasswordVault();
  var credentials = vault.Retrieve(appCredentialsName, userId);
 
  return credentials?.Password;
}

Сначала мы проверяем, что служба Windows Hello доступна. Затем просим службу подтвердить, что приложение использует пользователь, владелец учётной записи. Если пользователь прошёл проверку, то мы извлекаем ПИН-код для этого пользователя, который был сохранён туда при установке пин-кода Тинькофф.

И вот, при помощи 5 небольших методов мы интегрировали Windows Hello в приложение.

Автор: NikolaiKobzev

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js