userVerification: глубокое погружение

В этом документе обсуждается, что такое userVerification в WebAuthn, а также поведение браузера, которое возникает при указании userVerification во время создания ключа доступа или аутентификации.

Что такое «проверка пользователя» в WebAuthn?

Ключи доступа основаны на криптографии с открытым ключом. При создании ключа доступа генерируется пара открытого и закрытого ключей, закрытый ключ сохраняется поставщиком ключей доступа, а открытый ключ возвращается на сервер проверяющей стороны (RP) для хранения. Сервер может аутентифицировать пользователя, проверив подпись, подписанную тем же ключом доступа, используя парный открытый ключ. Флаг «присутствие пользователя» (UP) в учётных данных открытого ключа подтверждает, что кто-то взаимодействовал с устройством во время аутентификации.

Верификация пользователя — это дополнительный уровень безопасности, призванный подтвердить присутствие нужного человека во время аутентификации, а не просто какого-то другого, как это подтверждается присутствием пользователя. На смартфонах это обычно делается с помощью механизма блокировки экрана, будь то биометрическая проверка, PIN-код или пароль. Информация о том, была ли выполнена верификация пользователя, отображается в флаге «UV», который возвращается в данных аутентификатора во время регистрации ключа доступа и аутентификации.

Скриншот диалогового окна проверки пользователя в iCloud Keychain на macOS. В диалоговом окне пользователю предлагается войти с помощью Touch ID, отображается источник запроса аутентификации и имя пользователя. В правом верхнем углу диалогового окна находится кнопка «Отмена».
Диалоговое окно проверки пользователя в связке ключей iCloud на macOS.
Скриншот диалогового окна проверки пользователя в Chrome для Android. В этом диалоговом окне пользователю предлагается подтвердить свою личность с помощью распознавания лиц или отпечатков пальцев, а также отображается источник запроса аутентификации. В левом нижнем углу находится опция проверки с помощью PIN-кода.
Диалоговое окно проверки пользователя в Android Chrome.

Как UP и UV проверяются на сервере

Булевы флаги присутствия пользователя (UP) и проверки пользователя (UV) передаются серверу в поле данных аутентификатора. Во время аутентификации содержимое поля данных аутентификатора может быть проверено путем проверки подписи с использованием сохранённого открытого ключа. Пока подпись действительна, сервер может считать флаги подлинными.

Изображение структуры данных аутентификации. Слева направо каждый раздел структуры данных содержит следующие данные: «RP ID HASH» (32 байта), «FLAGS» (1 байт), «COUNTER» (4 байта, big-endian uint32), «ATTESTE CRED. DATA» (переменной длины, если присутствует) и «EXTENSIONS» (переменной длины, если присутствует (CBOR)). Раздел «FLAGS» расширен и отображает список возможных флагов, обозначенных слева направо: «ED», «AT», «0», «BS», «BE», «UV», «0» и «UP».
Поля данных аутентификатора в учетных данных открытого ключа.

При регистрации и аутентификации ключа доступа сервер должен проверить, является ли флаг UP true или false , а также является ли флаг UV true или false , в зависимости от требования.

Указание параметра userVerification

Согласно спецификации WebAuthn , проверяющая сторона может запрашивать верификацию пользователя с помощью параметра userVerification как при создании, так и при подтверждении учётных данных. Она принимает значения 'preferred' , 'required' или 'discouraged' , что означает соответственно:

  • 'preferred' (по умолчанию): использование метода проверки пользователя на устройстве является предпочтительным , но его можно пропустить, если он недоступен. Учётные данные ответа содержат значение флага UV: true , если проверка пользователя была выполнена, и false если UV не была выполнена.
  • 'required' : Требуется вызов метода проверки пользователя, доступного на устройстве. Если метод недоступен, запрос локально завершается ошибкой. Это означает, что учётные данные ответа всегда возвращаются с флагом UV, установленным в true .
  • 'discouraged' : использование метода пользовательской верификации не рекомендуется. Однако, в зависимости от устройства, пользовательская верификация может быть выполнена в любом случае, а флаг UV может содержать true или false .

Пример кода для создания ключа доступа:

const publicKeyCredentialCreationOptions = {
  // ...
  authenticatorSelection: {
    authenticatorAttachment: 'platform',
    residentKey: 'required',
    requireResidentKey: true,
    userVerification: 'preferred'
  }
};

const credential = await navigator.credentials.create({
  publicKey: publicKeyCredentialCreationOptions
});

Пример кода для аутентификации по ключу доступа:

const publicKeyCredentialRequestOptions = {
  challenge: /* Omitted challenge data... */,
  rpId: 'example.com',
  userVerification: 'preferred'
};

const credential = await navigator.credentials.get({
  publicKey: publicKeyCredentialRequestOptions
});

Какой вариант userVerification следует выбрать?

Значение userVerification , которое следует использовать, зависит от требований вашего приложения, а также от потребностей вашего пользовательского опыта.

Когда следует использовать userVerification='preferred'

Используйте userVerification='preferred' , если для вас удобство использования важнее защиты.

Существуют среды, в которых верификация пользователя скорее создает неудобства, чем обеспечивает защиту. Например, в macOS, где Touch ID недоступен (устройство не поддерживает его, отключено или устройство находится в режиме раскладушки), пользователю предлагается ввести системный пароль. Это создает неудобства, и пользователь может полностью отказаться от аутентификации. Если для вас важнее отсутствие неудобств, используйте userVerification='preferred' .

Скриншот диалогового окна ввода пароля в macOS, которое появляется при отсутствии Touch ID. В диалоговом окне содержится информация, например, источник запроса аутентификации и имя пользователя. В правом верхнем углу диалогового окна находится кнопка «Отмена».
Диалоговое окно ввода ключа доступа, отображаемое в macOS, когда Touch ID недоступен.

При userVerification='preferred' флаг UV имеет значение true , если верификация пользователя выполнена успешно, и false если верификация пропущена. Например, в macOS, где Touch ID недоступен, пользователю предлагается нажать кнопку, чтобы пропустить верификацию, а учётные данные открытого ключа содержат false флаг UV.

УФ-флаг может служить сигналом в вашем анализе рисков. Если попытка входа кажется рискованной из-за других факторов, вы можете предоставить пользователю дополнительные сложности при входе, если верификация не была выполнена.

Когда следует использовать userVerification='required'

Используйте userVerification='required' , если вы считаете, что и UP, и UV абсолютно необходимы.

Недостатком этого варианта является то, что пользователь может столкнуться с дополнительными трудностями при входе в систему. Например, в macOS, где Touch ID недоступен, пользователю предлагается ввести системный пароль.

Параметр userVerification='required' гарантирует, что на устройстве выполняется верификация пользователя. Убедитесь, что сервер проверяет, что флаг UV имеет true .

Заключение

Используя проверку пользователя, стороны, использующие ключ доступа, могут оценить вероятность входа владельца устройства в систему. Они сами решают, требовать ли проверку пользователя или сделать её необязательной, в зависимости от того, насколько критически механизм резервного входа влияет на пользовательский процесс. Убедитесь, что сервер проверяет флаги UP и UV для аутентификации пользователя с ключом доступа.