Passkeys и WebAuthn: что проверяет сервер и где остаётся закрытый ключ
Регистрация, challenge, область RP ID, пользовательское подтверждение и различия синхронизируемых и привязанных к устройству ключей.

Вместо общего секрета — пара ключей
WebAuthn позволяет подтверждать владение закрытым ключом без передачи этого ключа сайту. Сервер хранит открытый ключ и связанные сведения учётной записи, а authenticator выполняет криптографическую операцию. На вебе passkeys реализуются через этот API. Работа требует безопасного контекста, однако наличие HTTPS само по себе ещё не означает настроенную систему passkeys.
Браузер выступает посредником между приложением и authenticator. Последним может быть встроенный компонент платформы или отдельное устройство. Приложение получает результат операции, а не возможность произвольно читать закрытые ключи. При этом WebAuthn не является полным протоколом учётной записи: создание пользователя, назначение ролей, управление сессией после входа и восстановление доступа остаются задачами сервиса. Успешное подтверждение ключом отвечает на ограниченный вопрос о credential. Оно не определяет автоматически, какие документы, платежи или административные функции разрешены связанной с ним записи.
Создание credential и его привязка
Регистрация начинается с параметров от сервера, включая challenge и сведения relying party. Клиент вызывает navigator.credentials.create с publicKey. Authenticator создаёт credential с участием пользовательского согласия и возвращает публичные сведения, необходимые для проверки и последующего входа.
Проверка не сводится к сохранению присланного браузером идентификатора. Сервер сопоставляет challenge, ожидаемый origin и другие поля результата; attestation, если она используется, рассматривается отдельно. Публичный ключ связывается с конкретной учётной записью. Новое credential можно добавить и существующему пользователю, поэтому регистрация ключа не обязана означать создание нового профиля. Диаграмма MDN разделяет взаимодействие приложения, сервера, браузера и authenticator: каждый участник выполняет свою часть. В частности, код страницы не получает закрытый ключ в ответе create. Его отсутствие на сервере является свойством модели, а не результатом того, что разработчик просто скрыл поле в интерфейсе.

Параметры создания не взаимозаменяемы
residentKey описывает требование обнаруживаемого credential. Значение required требует его создания и приводит к ошибке, если это невозможно; preferred выражает предпочтение и допускает другой результат. Такой параметр отличается от userVerification, который задаёт требования к локальной проверке пользователя.
excludeCredentials помогает не создавать повторно credential для уже зарегистрированной связи. Список поддерживаемых алгоритмов сообщает, какие типы ключей сервер сможет обработать. Если совместимого варианта нет, операция не должна считаться успешной только из-за показанного окна. RP ID задаёт область действия credential и не содержит схему или порт как обычный origin. Поэтому ID сайта и адрес страницы нельзя механически копировать друг в друга. Создание ключа, выбор его области и последующая проверка должны согласовываться: authenticator, браузер и сервер используют эти параметры в разных частях одной операции, а не как независимые пожелания дизайна.
Вход подтверждает свежий запрос
При входе сервер снова выдаёт challenge, а клиент вызывает navigator.credentials.get. В запросе могут перечисляться допустимые credentials. Пустой allowCredentials допускает выбор подходящего обнаруживаемого credential без заранее переданного перечня идентификаторов. Это не разрешение использовать ключ произвольного другого сайта: область RP ID остаётся частью проверки.
Authenticator подписывает данные ответа, а сервер проверяет подпись сохранённым открытым ключом и сопоставляет ожидаемый контекст. Challenge связывает результат с текущей операцией, поэтому старый подписанный ответ не должен приниматься как новое подтверждение. В request options также существуют userVerification, transport hints и timeout. Timeout является подсказкой браузеру, а не гарантированным сроком жизни серверной операции. Успех локального окна не отменяет серверную проверку результата. Напротив, только после согласования ожидаемого запроса и проверенного assertion сервис может создать нужную ему сессию или подтвердить дополнительное действие пользователя.
Касание не равно проверке личности
Спецификация различает user presence и user verification. Presence означает подтверждённое взаимодействие пользователя с authenticator, например касание. Само по себе такое действие не различает владельца и другого человека, который физически получил устройство. Verification использует локальный механизм, например PIN или биометрическую проверку, чтобы выполнить дополнительную авторизацию операции.
Соответствующие сведения отражаются в данных authenticator отдельными флагами UP и UV. Поэтому интерфейсная формулировка «подтвердите вход» не сообщает серверу весь смысл результата. Требования операции и фактически выполненная проверка должны совпадать. Биометрия также не является обязательным единственным способом WebAuthn: подходящий PIN может участвовать в той же модели. Схема структуры authenticator data показывает, что флаги — часть подписываемого протокольного результата, а не произвольная галочка JavaScript-интерфейса. Термин «без пароля на сайте» описывает отсутствие общего секрета, вводимого в форму, но не запрещает локальное подтверждение на устройстве.

| Понятие | Что обозначает |
|---|---|
| User presence | Факт взаимодействия с authenticator |
| User verification | Локальная проверка через доступный механизм |
| RP ID | Область relying party для credential |
| Challenge | Контекст текущего запроса сервера |
Источник: W3C: WebAuthn definitions
Синхронизация — отдельное свойство хранения
FIDO различает синхронизируемые и device-bound passkeys. В первом случае provider может сделать credential доступным на других устройствах пользователя через защищённую синхронизацию. Во втором ключ остаётся связан с определённым устройством, включая отдельный аппаратный security key. Эти варианты не следует смешивать с противопоставлением «телефон или USB»: способ подключения и возможность резервирования — разные характеристики.
Локальная биометрическая обработка не отправляет сайту отпечаток. Сервис получает результат криптографического подтверждения и сведения о выполненной проверке. При смене устройства доступность синхронизированного ключа зависит от выбранного provider и доступа к его учётной записи. Наличие passkey на одном устройстве поэтому не доказывает, что он автоматически появится в любом другом менеджере. Модель синхронизации также не означает экспорт закрытого ключа в код сайта. Она относится к управлению credentials на пользовательской стороне, а сервер продолжает выполнять проверку открытым ключом.
Несколько ключей и жизнь учётной записи
Обнаруживаемые credentials позволяют выбирать подходящую учётную запись без предварительного ввода имени и передачи её credential ID сервером. Необнаруживаемый вариант требует сначала определить пользователя и передать соответствующий идентификатор. Passkeys используют обнаруживаемую модель, но другие WebAuthn-сценарии могут иметь иные условия.
Одна учётная запись может иметь несколько зарегистрированных credentials. Потеря отдельного устройства, удаление credential и закрытие сессии на сайте являются разными событиями. Управление самим authenticator, включая удаление хранимых credentials, не предоставляется странице как произвольный административный API. Поэтому отзыв доступа сервисом и физическое наличие ключа не обязаны меняться одновременно: сервер может перестать принимать credential, который ещё существует на устройстве.


