
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 мы предлагаем пользователю подключить эту службу:

Если пользователь соглашается, то необходимо его аутентифицировать, для этого мы используем следующий код:
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="pin">ПИН-код доступа</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 в приложение.
