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

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

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

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

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

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

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

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

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

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

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

Согласно спецификации WebAuthn , RP может запросить проверку пользователя с помощью параметра 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' вы можете гарантировать, что на устройстве выполняется проверка пользователя. Убедитесь, что сервер проверяет true флага UV.

Заключение

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