Неправильные настройки сервера WebAuthn могут привести к проблемам с пользовательским опытом и нарушить работу существующих passkeys. Это руководство поможет разработчикам правильно настроить серверы WebAuthn.
Vincent
Created: August 20, 2025
Updated: August 21, 2025
See the original blog version in English here.
Our mission is to make the Internet a safer place, and the new login standard passkeys provides a superior solution to achieve that. That's why we want to help you understand passkeys and its characteristics better.
Passkeys и лежащий в их основе протокол WebAuthn производят революцию в сфере аутентификации. Однако правильная настройка сервера WebAuthn может оказаться непростой задачей. Неправильные конфигурации могут не только создать уязвимости, но и нарушить работу существующих passkeys, если вам понадобится изменить их позже. Эта статья поможет лучше понять часто сложные спецификации WebAuthn и даст советы, какие настройки лучше всего подходят для вашего случая.
Recent Articles
📝
Как создать верификатор цифровых учетных данных (руководство для разработчиков)
📝
Как создать эмитент цифровых удостоверений (руководство для разработчиков)
📖
Резидентный ключ WebAuthn: обнаруживаемые учетные данные как Passkeys
🔑
Доступ по физическим пропускам и Passkeys: техническое руководство
🔑
Внедрение обязательной MFA и переход на Passkeys: лучшие практики
WebAuthn работает с тремя основными участниками:
Далее мы опишем общий поток данных во время процесса аутентификации (входа или регистрации).
Ben Gould
Head of Engineering
I’ve built hundreds of integrations in my time, including quite a few with identity providers and I’ve never been so impressed with a developer experience as I have been with Corbado.
Более 10 000 разработчиков доверяют Corbado и делают интернет безопаснее с помощью passkeys. Есть вопросы? Мы написали более 150 статей о passkeys.
Присоединяйтесь к сообществу PasskeysОписанный выше высокоуровневый процесс описывает процессы регистрации и входа с помощью WebAuthn. Passkeys построены на основе WebAuthn. Изначально термин «passkeys» использовался как более запоминающийся и нетехнический термин для описания того же самого. Более того, passkeys предоставляют больше возможностей по сравнению со стандартным WebAuthn, например, возможность синхронизировать passkeys через облачные аккаунты или менеджеры паролей.
Чтобы лучше понять следующие разделы, определим несколько важных терминов протокола WebAuthn для общего понимания.
Резидентные ключи (RK) и нерезидентные ключи (NRK) — это два типа криптографических ключей, используемых в протоколе WebAuthn, и они различаются в основном местом хранения и механизмом извлечения.
Определение:
Резидентные ключи хранятся непосредственно на самом аутентификаторе. Это может быть ключ безопасности (например, YubiKey), защищенный анклав (secure enclave) платформы (например, Secure Enclave на iPhone) или доверенный платформенный модуль (TPM) на ноутбуке. Условный интерфейс (Conditional UI, автозаполнение passkey) работает только для резидентных ключей, и рабочая группа WebAuthn в настоящее время требует, чтобы ключ был резидентным, чтобы считаться passkey.
Резидентные ключи часто называют обнаруживаемыми учетными данными, потому что клиент может обнаружить список возможных ключей от аутентификатора, которые соответствуют ID доверяющей стороны (rpID), и показать список возможных / сохраненных идентификаторов пользователя (например, email, номера телефонов, имена пользователей) на устройстве.
На следующем скриншоте вы видите список всех резидентных ключей (ID учетных данных, rpID, имя пользователя, отображаемое имя), которые хранятся на YubiKey. Нерезидентных ключей в списке нет, так как они не хранятся на аутентификаторе:
Процесс входа:
Источник: William Brown
Во время процесса входа доверяющая сторона отправляет запрос без указания учетных данных клиенту (браузеру), который начинает опрашивать аутентификатор (на схеме: ключ безопасности). Аутентификатор обнаруживает все резидентные ключи для соответствующей доверяющей стороны, и клиент (браузер) выбирает нужный резидентный ключ. Этот резидентный ключ используется для подписи challenge. Подпись отправляется от аутентификатора через клиента к доверяющей стороне.
Преимущества:
Недостатки:
Сценарии использования: Идеально подходят для устройств, на которых пользователь часто аутентифицируется, например, личные смартфоны или ноутбуки.
Определение:
Нерезидентные ключи, в отличие от резидентных, не хранятся на аутентификаторе. Вместо этого аутентификатор генерирует новую пару ключей (на основе своего внутренне защищенного мастер-ключа) и отправляет публичный ключ этой новой пары на сервер (доверяющую сторону) вместе с ID учетных данных (который содержит начальное значение, seed) во время регистрации. Сервер затем связывает этот публичный ключ с учетной записью пользователя. Для последующих аутентификаций аутентификатор заново выводит приватный ключ, получая ID учетных данных, извлекая seed и комбинируя его с мастер-ключом. Поскольку ключ доступен только временно в защищенной памяти аутентификатора, в криптографии его иногда называют эфемерным ключом.
Нерезидентные ключи также часто называют необнаруживаемыми учетными данными, потому что аутентификатор не может обнаружить / искать ключи для определенного ID доверяющей стороны (rpID). Без ID учетных данных аутентификатор даже не знает, что ключ может существовать.
Процесс входа:
Источник: William Brown
Во время процесса входа доверяющая сторона должна сначала определить, какой пользователь запрашивает аутентификацию (например, запросив идентификатор пользователя, такой как email, номер телефона или имя пользователя), а затем отправляет известные ей ID учетных данных для запрашивающего пользователя клиенту (браузеру). Клиент пересылает их аутентификатору (здесь: ключ безопасности). Аутентификатор использует ID учетных данных вместе с мастер-ключом аутентификатора для получения временного приватного ключа, подписывает challenge сгенерированным ключом и возвращает его клиенту (здесь: браузер), который пересылает его доверяющей стороне. Нерезидентные ключи изначально использовались как второй фактор до появления passkeys. Поэтому идентификация пользователя была частью обычного процесса входа.
Преимущества:
Недостатки:
Сценарии использования: Идеально подходят для роуминговых аутентификаторов, таких как ключи безопасности (например, YubiKeys), которые используются на нескольких сервисах или платформах.
Представьте, что у вас есть ключ безопасности (например, YubiKey), и вы регистрируете его в двух онлайн-сервисах: Сервис A и Сервис B. Для Сервиса A вы используете резидентный ключ. Для Сервиса B — нерезидентный ключ. Когда вы аутентифицируетесь в Сервисе A, вы просто касаетесь своего ключа безопасности, и вы в системе — не нужно указывать имя пользователя. Для Сервиса B вам сначала нужно будет ввести свое имя пользователя в браузере / нативном приложении. Затем сервис отправит связанный ID учетных данных на ваш ключ безопасности, который заново сгенерирует эфемерный приватный ключ для аутентификации.
По сути, хотя и резидентные, и нерезидентные ключи повышают безопасность за счет использования криптографической аутентификации, их пользовательский опыт и механизмы хранения различаются, удовлетворяя разные сценарии использования.
Условный интерфейс (Conditional UI) — это знаковая особенность passkeys / WebAuthn. Он еще больше облегчает жизнь пользователю, поскольку ему не только не нужно помнить пароль, но и не нужно помнить идентификатор пользователя (например, email, номер телефона, имя пользователя), с которым он зарегистрировался в доверяющей стороне. Особенно в случаях, когда сервисы доверяющих сторон используются лишь изредка, это огромный шаг вперед.
Это работает, потому что как только открывается страница входа, сервер доверяющей стороны отправляет challenge в фоновом режиме клиенту (помните, что в этом вызове не требуется отправлять ID учетных данных). Клиент берет этот challenge, проверяет, какие passkeys на этом аутентификаторе соответствуют ID доверяющей стороны, и предлагает выбор через меню автозаполнения, где пользователь может выбрать соответствующий passkey.
Более того, это также избавляет пользователя от лишнего клика по кнопке входа, потому что как только passkey выбран из меню автозаполнения, процесс входа начинается.
Условный интерфейс (Conditional UI, автозаполнение passkeys) работает только для резидентных ключей.
CTAP — это основополагающий протокол стандарта FIDO2, который обеспечивает связь между клиентами (например, браузерами) и аутентификаторами (например, ключами безопасности YubiKeys или смартфонами). Чтобы лучше понять CTAP, давайте сначала кратко рассмотрим различные версии протокола, прежде чем анализировать их влияние на резидентные и нерезидентные ключи.
Более ранняя версия, часто называемая Universal 2nd Factor (U2F), была в основном разработана для двухфакторной аутентификации. В U2F сервер предоставляет challenge, а аутентификатор — ответ, доказывая владение приватным ключом. Однако U2F не поддерживает резидентные ключи, что означает, что всегда требуется поиск на стороне сервера, чтобы определить, какой ключ использовать для пользователя, так как это было частью процесса запроса второго фактора.
Преемник U2F, CTAP2, ввел поддержку резидентных ключей, что позволило осуществлять аутентификацию без пароля и имени пользователя. С резидентными ключами аутентификатор хранит имя пользователя и ID учетных данных (вместе с ID доверяющей стороны), что устраняет необходимость для сервера доверяющей стороны предоставлять их во время аутентификации. Это значительный шаг к более удобному UX.
Однако CTAP2 сопряжен с трудностями. Одной из заметных проблем является управление резидентными ключами. Например, удаление определенного резидентного ключа на устройстве CTAP2.0 часто требует полного сброса устройства (что также сбрасывает ваш мастер-ключ, а значит, все ваши нерезидентные ключи перестанут работать), что неудобно для пользователя и может быть проблематично в сценариях, где на одном устройстве хранится несколько резидентных ключей. Это делает резидентные ключи на устройстве CTAP2.0 серьезным обязательством. Вы точно не захотите случайно заполнить то ограниченное пространство, которое у вас часто есть, особенно на ключах безопасности (например, YubiKeys).
CTAP2.1 — это последующая версия CTAP2, добавляющая дополнительные функции и улучшения в протокол. Некоторые ключевые моменты CTAP 2.1 включают:
Рассмотрев резидентные и нерезидентные ключи, а также различные версии CTAP, теперь мы более подробно проанализируем сторону доверяющей стороны и, следовательно, сторону сервера WebAuthn.
Гибкость (а также сложность) WebAuthn во многом обусловлена его серверными настройками, особенно в объекте authenticatorSelection. Этот объект направляет клиента в выборе правильного аутентификатора для задачи.
{ "rp": { "name": "corbado.com", "id": "corbado.com" }, "user": { "id": "dGVzdefEyMjE", "name": "test-username", "displayName": "test-username" }, "challenge": "mhanjsapJjCNaN_Ttasdfk1C0DymR-V_w_0UVOPsdfdfJG2ON_FK5-ODtqp33443tgqHzuuDjv-NUUmMAE4hg", "pubKeyCredParams": [ { "type": "public-key", "alg": -7 }, { "type": "public-key", "alg": -257 } ], "timeout": 60000, "excludeCredentials": [], "authenticatorSelection": { "authenticatorAttachment": "platform", "residentKey": "preferred", "requireResidentKey": false, "userVerification": "preferred" }, "attestation": "none", "extensions": { "credProps": true } }
authenticatorAttachment
#Этот параметр сервера указывает, как аутентификатор подключен к устройству клиента. Он дает представление о том, как аутентификатор взаимодействует с клиентом:
Возможные значения
platform
: Указывает, что аутентификатор привязан к платформе клиента и,
следовательно, не является съемным.cross-platform
: Указывает, что аутентификатор не привязан к платформе клиента и
может использоваться на нескольких устройствах.Сценарии использования и примеры
platform
: Примеры включают сканер отпечатков пальцев, встроенный в ноутбук, или
систему распознавания лиц на телефоне, например, Face ID, Touch ID или
Windows Hello.cross-platform
: Примеры включают USB-ключи безопасности (например, YubiKeys),
Bluetooth-устройства или NFC-карты.residentKey
#В спецификации WebAuthn Level 1 этот параметр сервера назывался requireResidentKey
и мог
принимать булевы значения true
(аутентификатор должен создать резидентный ключ) или
false
(аутентификатор должен создать нерезидентный ключ).
WebAuthn Level 2
заменил этот параметр новым параметром residentKey
:
Возможные значения
required
: Аутентификатор должен создать резидентный ключ (если это невозможно,
операция должна завершиться ошибкой).preferred
: Аутентификатор должен попытаться создать резидентный ключ (если это
невозможно, он должен создать нерезидентный ключ).discouraged
: Аутентификатор должен создать нерезидентный ключ (если это
невозможно, операция должна завершиться ошибкой).Сценарии использования и примеры
required
: Идеально для сценариев, где желателен вход без имени пользователя или
где пользователи должны аутентифицироваться только с ранее зарегистрированных устройств
(добавляя дополнительный уровень безопасности путем привязки учетных данных пользователя
к конкретному устройству).preferred
: Подходит для сценариев, когда веб-сервис хочет предоставить наилучший
UX для входа, если это возможно (через резидентные ключи), но все же хочет поддерживать
нерезидентные ключи, если резидентные ключи невозможны.discouraged
: Сервис хочет предложить
аутентификацию с помощью passkey, а также хочет
убедиться, что пользователи могут использовать любой аутентификатор, даже без
возможности хранения, не привязывая учетные данные к конкретному устройству.userVerification
#Верификация пользователя (User verification) относится к процессу, который гарантирует, что человек, взаимодействующий с аутентификатором, является законным владельцем, обычно требуя определенного жеста аутентификации, такого как ввод PIN-кода, предоставление отпечатка пальца или использование распознавания лиц.
Иногда подтверждение присутствия пользователя (User presence, UP) также упоминается или используется аналогично верификации пользователя, но на самом деле есть некоторые различия. Подтверждение присутствия только подтверждает, что кто-то — кто угодно — физически присутствует и взаимодействует с устройством. Оно не проверяет личность этого человека. Простого касания ключа безопасности, без каких-либо дальнейших проверок личности, может быть достаточно для подтверждения присутствия. Для passkeys / WebAuthn пользователь всегда должен присутствовать.
Возможные значения
required
: Операция должна иметь
верификацию пользователя.preferred
: Операция должна иметь
верификацию пользователя, если это возможно, но
может продолжаться и без нее.discouraged
: Операция не должна иметь
верификацию пользователя.Сценарии использования и примеры
required
: Идеально для высокозащищенных приложений, таких как
банкинг или
здравоохранение, где проверка личности пользователя
(например, через отпечаток пальца или PIN-код) имеет решающее значение.preferred
: Полезно для общих приложений, где дополнительная безопасность является
бонусом, но не является строго необходимой.discouraged
: Подходит для операций с низким риском или сценариев, где
верификация пользователя может быть неудобной.Шаблон
authenticatorAttachment
: platform
residentKey
: required
userVerification
: required
Пример: Корпоративное приложение хочет, чтобы сотрудники входили в систему без паролей на своих корпоративных ноутбуках, используя встроенные сканеры отпечатков пальцев. Учетные данные хранятся на устройстве, и пользователь должен каждый раз подтверждать свою личность с помощью отпечатка пальца.
Шаблон
authenticatorAttachment
: cross-platform
residentKey
: required
userVerification
: required
Пример: Пользователь регистрирует ключ безопасности (например, YubiKey) для своего онлайн-банкинга. Он может использовать этот ключ для аутентификации на любом устройстве, предоставив ключ безопасности, без необходимости вводить имя пользователя.
Многие аппаратные ключи безопасности (например, YubiKeys) имеют встроенные ограничения по объему хранилища. Это ограничение связано с физической памятью, доступной на устройстве, и конструктивными соображениями производителя.
Пример: YubiKey может хранить только 20 резидентных ключей. Как только этот лимит достигнут, новые резидентные ключи не могут быть добавлены без удаления существующих.
Решение:
Различные аутентификаторы могут по-разному обрабатывать запросы на резидентные ключи. Некоторые могут по умолчанию создавать резидентный ключ, даже если это не было явно запрошено, в то время как другие могут требовать явных инструкций.
Непоследовательное поведение для разных параметров
сервера WebAuthn на разных платформах является
серьезной проблемой. Например, iOS всегда создает
резидентный ключ независимо от переданных параметров
сервера WebAuthn, в то время как
Android требует явного согласия (например, с
residentKey: preferred
или residentKey: required
).
Кроме поведения, еще хуже то, что на основе данных, хранящихся на стороне сервера, вы не можете со 100% уверенностью сказать, являются ли сохраненные учетные данные резидентным или нерезидентным ключом. Вместо этого вы можете выполнить несколько проверок и сузить круг (см. ниже), но все равно придется надеяться, что поведение учетных данных соответствует вашим ожиданиям.
Причина в том, что есть предложение WebAuthn хранить информацию о типе учетных данных
(резидентный или нерезидентный ключ) в
расширении свойств учетных данных
(clientExtensionResults.credProps.rk
, которое равно true
или false
). Однако
предоставление этой информации RP не гарантируется, так как все расширения WebAuthn
являются необязательными, например, iOS не отправляет
его (поэтому вы не знаете, резидентный это ключ или нет).
В ходе нашего исследования мы пытались протестировать поведение на разных платформах и
аутентификаторах (Windows 10, Windows 11,
Android 7,
Android 13, iOS17, macOS Ventura, YubiKey) с двумя
демонстрационными страницами WebAuthn, которые предоставляют более подробную информацию о
созданных учетных данных: https://webauthn.io и
https://webauthntest.identitystandards.io/.
Последняя предлагает возможность работать с устаревшим свойством requireResidentKey
(WebAuthn Level 1) и даже комбинировать его со свойством residentKey
(WebAuthn Level 2).
Однако результаты не были надежными (например, для iOS
указывался нерезидентный ключ, но условный интерфейс явно
работал).
Самая надежная схема проверки, которую мы нашли, выглядит следующим образом:
residentKey: required
и учетные данные успешно созданы -> это резидентный
ключresidentKey: preferred
или residentKey: discouraged
, переходите к
следующей проверкеcredProps.rk
и хранится ли оно в учетных данных на
сервере?
credProps.rk = true
, учетные данные являются резидентным ключомcredProps.rk = false
, учетные данные являются нерезидентным ключомcredProps
пусто, то тип учетных данных неизвестенКак видите, это помогает сузить круг, но все же остается вариант «неизвестно», и вы не можете определить тип ключа со 100% уверенностью.
Это также согласуется с выводами Уильяма Брауна из SUSE в его замечательной статье, где он описывает, как ключи безопасности (например, YubiKeys) могут стать бесполезными, если доверяющие стороны требуют резидентные ключи (мы расширили его таблицу):
В таблице вы видите, был ли создан резидентный ключ (true
), нерезидентный ключ (false
)
или произошло что-то еще для различных опций резидентного ключа сервера WebAuthn.
Решение:
residentKey
в required
(обратите внимание, что это может привести к другим проблемам с
аутентификаторами с ограниченной емкостью резидентных ключей, см. выше).Если пользователь достигает предела хранилища на своем ключе безопасности (например, YubiKey), он может столкнуться с ошибками или не сможет зарегистрировать новые учетные данные. Это может привести к замешательству и разочарованию.
Решение:
Как вы видели выше, выбранные вами настройки сервера WebAuthn могут значительно повлиять на пользовательский опыт и безопасность вашего процесса аутентификации. Важно понимать нюансы этих настроек, чтобы принимать обоснованные решения.
Резидентные vs. Нерезидентные ключи: Если большинство ваших пользователей в основном получают доступ к вашему сервису с личных устройств, таких как смартфоны или ноутбуки, резидентные ключи — подходящий выбор. Резидентные ключи хранятся на самом устройстве и предлагают безупречный опыт аутентификации для пользователей, которые часто используют одно и то же устройство. Однако для пользователей, которые используют ключи безопасности (например, YubiKeys), более подходящими могут быть нерезидентные ключи.
Настройки верификации пользователя (UV): В зависимости от уровня безопасности,
которого вы хотите достичь, вы можете решить, насколько строгим должен быть процесс
верификации пользователя. Если вы стремитесь к высокой
безопасности, рекомендуется требовать PIN-код, отпечаток пальца или распознавание лиц
(userVerification: preferred
или userVerification: required
).
Аттестация (Attestation) и надежность: Аттестация позволяет проверить происхождение и целостность аутентификатора. Решите, хотите ли вы доверять всем аутентификаторам или только тем, что произведены определенными компаниями. Это может быть критически важно, если вы работаете с конфиденциальными данными и хотите обеспечить использование только высококачественных, доверенных аутентификаторов.
Резервные механизмы: Всегда имейте резервный механизм. Если пользователь теряет свой аутентификатор или он выходит из строя, у него должен быть альтернативный способ доступа к своей учетной записи. Это могут быть резервные коды, SMS-подтверждение, магические ссылки по электронной почте или другие методы многофакторной аутентификации.
Непрерывное обучение: Ландшафт passkeys и WebAuthn постоянно развивается. Будьте в курсе последних разработок, уязвимостей и исправлений. Поощряйте вашу команду разработчиков участвовать в семинарах, вебинарах и конференциях, посвященных passkeys и WebAuthn.
Онбординг и обучение пользователей: Внедряя аутентификацию с помощью passkey, убедитесь, что ваши пользователи понимают ее преимущества и как она работает. Предлагайте четкие инструкции в процессе регистрации и предоставляйте ресурсы (например, FAQ или видеоуроки), чтобы помочь пользователям в настройке и использовании passkeys.
Придерживаясь этих лучших практик, разработчики и продакт-менеджеры могут обеспечить эффективное внедрение аутентификации с помощью passkey, находя баланс между безопасностью и пользовательским опытом.
Если вы хотите внедрить passkeys для массового использования на вашем веб-сайте или в приложении и вам не нужно поддерживать ключи безопасности (например, YubiKeys), поскольку большинство ваших пользователей будут просто использовать свой смартфон или ноутбук, мы рекомендуем следующие настройки.
authenticatorAttachment
: platform
residentKey
: required
userVerification
: required
Преимущества:
Настройки сервера WebAuthn, хотя и сложны, предлагают надежную и гибкую основу для аутентификации. Освоение этих настроек имеет решающее значение, поскольку речь идет не просто о внедрении нового стандарта; речь идет о фундаментальном улучшении безопасности и эффективности аутентификации пользователей.
По сути, понимание настроек сервера WebAuthn — это инвестиция в создание более безопасных, эффективных и перспективных приложений. По мере развития цифрового ландшафта, глубокое знание таких технологий будет незаменимым. Чтобы оставаться в курсе, присоединяйтесь к нашему сообществу passkeys или подпишитесь на нашу рассылку ниже.
Related Articles
Table of Contents