Руководство для разработчиков по WebAuthn и внедрению ключей доступа. Скачайте шпаргалку в формате PDF или используйте этот сайт, где собрана вся информация.
Lukas R.
Создано: 6 марта 2024 г.
Обновлено: 3 июля 2026 г.

Эта страница переведена автоматически. Прочитайте оригинальную версию на английском здесь.
Скачайте полную Шпаргалку по ключам доступа бесплатно и получите всю необходимую информацию.
Полное руководство разработчика по ключам доступа
Получите справочник для разработчиков по ключам доступа, охватывающий поддержку платформ, поведение браузеров, лучшие практики UX и советы по интеграции.

Аутентификация с помощью ключей доступа основана на двух процессах, также называемых церемониями: регистрации (также известной как фаза аттестации) и входа (также известного как фаза утверждения).
Каждая фаза требует случайного вызова (challenge), сгенерированного сервером, который подписывается аутентификатором и отправляется обратно на сервер WebAuthn для проверки пользователя.
Экспериментируйте с passkey-флоу в Passkeys Debugger.
В церемонии регистрации используются два основных объекта: PublicKeyCredentialCreationOptions и attestation.
В церемонии входа используются два основных объекта: PublicKeyCredentialRequestOptions и assertion.
Посмотрите, сколько людей действительно используют passkeys.
Для регистрации и входа с помощью ключей доступа используются четыре основных объекта:
В этом разделе также объясняется объект authenticatorSelection, который используется в PublicKeyCredentialCreationOptions.
Igor Gjorgjioski
Head of Digital Channels & Platform Enablement, VicRoads
We hit 80% mobile passkey activation across 5M+ users without replacing our IDP.
See how VicRoads scaled passkeys to 5M+ users — alongside their existing IDP.
Read the case studyPublicKeyCredentialCreationOptions является центральным объектом фазы аттестации (Регистрации). Он создается и возвращается сервером WebAuthn.
{ "PublicKeyCredentialCreationOptions": { "rp": { "id": "passkeys.eu", "name": "Corbado Passkeys Demo" }, "user": { "displayName": "john.doe", "id": "dXNyLZ….DU10Tc", "name": "john@doe.com" }, "challenge": "888fix4Bus...pHHr3Y", "pubKeyCredParams": [ { "alg": -7, "type": "public-key" }, { "alg": -257, "type": "public-key" } ], "excludeCredentials": [], "authenticatorSelection": { "authenticatorAttachment": "platform", "residentKey": "required", "userVerification": "required" }, "attestation": "none", "extensions": {} } }
Объект содержит следующие атрибуты:
Подпишитесь на наш Passkeys Substack, чтобы получать новости.
PublicKeyCredentialRequestOptions является центральным объектом фазы утверждения (Входа). Он создается и возвращается сервером WebAuthn.
{ "publicKeyCredentialRequestOptions": { "challenge": "pT7HMA-…dFPHk", "timeout": 500, "rpId": "passkeys.eu", "userVerification": "preferred", "allowCredentials": [], "extensions": [] } }
Объект содержит следующие атрибуты:
Во время церемонии аттестации / регистрации аутентификатор возвращает этот Ответ на регистрацию (Registration Response). Вы можете попробовать это сами в Отладчике ключей доступа (Passkeys Debugger).
{ "authenticatorAttachment": "platform", "id": "JKZbixUfKN_aZtimefYT-OjH5dw", "rawId": "JKZbixUfKN_aZtimefYT-OjH5dw", "response": { "attestationObject": { "fmt": "none", "attStmt": {}, "authData": { "rpIdHash": "PpZrl-Wqt-OFfBpyy2SraN1m7LT0GZORwGA7-6ujYkM", "flags": { "userPresent": true, "userVerified": true, "backupEligible": true, "backupStatus": true, "attestedData": true, "extensionData": false }, "counter": 0, "aaguid": { "raw": "fbfc3007-154e-4ecc-8c0b-6e020557d7bd", "name": "iCloud Keychain" }, "credentialID": "JKZbixUfKN_aZtimefYT-OjH5dw", "credentialPublicKey": "pQECAyYgASFYIPWLalDzyxIDmAADvfK8iNM5To50kh7TyPH-teEz8RMdIlgg3D7bPIWQJ8z-WFn3zdYZzJw9c7mhPdmflQqD9vV7efA", "parsedCredentialPublicKey": { "keyType": "EC2 (2)", "algorithm": "ES256 (-7)", "curve": 1, "x": "9YtqUPPLEgOYAAO98ryI0zlOjnSSHtPI8f614TPxEx0", "y": "3D7bPIWQJ8z-WFn3zdYZzJw9c7mhPdmflQqD9vV7efA" } } }, "clientDataJSON": { "type": "webauthn.create", "challenge": "k2p6f-upzP_hc6NZvmMAxiI0VSTeQIeXXVRGW62LTj0", "origin": "https://www.passkeys-debugger.io", "crossOrigin": false }, "transports": ["hybrid", "internal"], "authenticatorData": "PpZrl-Wqt-OFfBpyy2SraN1m7LT0GZORwGA7-6ujYkNdAAAAAPv8MAcVTk7MjAtuAgVX170AFCSmW4sVHyjf2mbYpnn2E_jox-XcpQECAyYgASFYIPWLalDzyxIDmAADvfK8iNM5To50kh7TyPH-teEz8RMdIlgg3D7bPIWQJ8z-WFn3zdYZzJw9c7mhPdmflQqD9vV7efA", "publicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9YtqUPPLEgOYAAO98ryI0zlOjnSSHtPI8f614TPxEx3cPts8hZAnzP5YWffN1hnMnD1zuaE92Z-VCoP29Xt58A", "publicKeyAlgorithm": -7 }, "type": "public-key", "clientExtensionResults": {} }
Аттестация содержит некоторые важные компоненты, такие как attestationObject, algorithm и флаги transport.
Взято из Спецификации W3C Webauthn
attestationObject — это объект в кодировке CBOR, содержащий информацию о вновь созданных учетных данных, открытом ключе и другие соответствующие данные:
Подробнее читайте о расширениях.
Ключи доступа генерируются с помощью алгоритмов COSE, при этом используемый алгоритм указывается в атрибуте algorithm объекта parsedCredentialPublicKey в объекте аттестации.
Ниже представлен обзор наиболее важных алгоритмов COSE:
Свойство transports указывает механизмы, с помощью которых аутентификатор может связываться с клиентом. Некоторые общие, типичные комбинации значений:
Во время церемонии утверждения / входа аутентификатор возвращает этот Ответ на вход (Login Response). Вы можете попробовать это сами в Отладчике ключей доступа (Passkeys Debugger).
{ "id": "JKZbixUfKN_aZtimefYT-OjH5dw", "rawId": "JKZbixUfKN_aZtimefYT-OjH5dw", "type": "public-key", "authenticatorAttachment": "platform", "response": { "authenticatorData": { "rpIdHash": "PpZrl-Wqt-OFfBpyy2SraN1m7LT0GZORwGA7-6ujYkM", "flags": { "userPresent": true, "userVerified": true, "backupEligible": true, "backupStatus": true, "attestedData": false, "extensionData": false }, "counter": 0 }, "clientDataJSON": { "type": "webauthn.get", "challenge": "GCVkITWbe2l2dttsn_DgJYvH9QPHPDo0ygWgcgI6B7U", "origin": "https://www.passkeys-debugger.io", "crossOrigin": false, "other_keys_can_be_added_here": "do not compare clientDataJSON against a template. See https://goo.gl/yabPex" }, "signature": "MEQCIA-orC8N2KKWOxyY17BWP8lB-Be5to9btXRnJZf2SLhXAiBGxJe5Eu5LwOTbsyzAYmIXHOhlC3pN7s7Q1fRLvEW57g", "userHandle": "_FKz1uwqmR_3yGq6hJntzoIFwFC_d1u_53YRELh0KlE" } }
Утверждение содержит некоторые важные компоненты, такие как flags, signature и userHandle.
Вот обзор наиболее важных флагов (flags) и их комбинаций:
Подпись (signature) используется для проверки того, что пользователь, пытающийся войти в систему, действительно обладает закрытым ключом. Подпись создается путем конкатенации authenticatorData и clientDataHash (то есть версии ClientDataJSON в формате SHA-256) и подписания результата закрытым ключом (в аутентификаторе). Для проверки с помощью открытого ключа мы также конкатенируем authenticatorData и clientDataHash. Если результат проверки возвращает true, аутентификация прошла успешно.
userHandle — это фактический user_id. Подробнее об user_id читайте в разделе 4.1 Схема базы данных.
Объект authenticatorSelection позволяет серверу задавать настройки для аутентификатора и создания учетных данных со следующими значениями:
Резидентные ключи (также называемые обнаруживаемыми учетными данными, Discoverable Credential): Резидентные ключи хранятся в аутентификаторе и извлекаются во время аутентификации. Таким образом, клиент может обнаружить список возможных ключей; именно поэтому Условный UI (Conditional UI) требует резидентных ключей. Нерезидентные ключи (также называемые необнаруживаемыми учетными данными, Non-Discoverable Credential): В случае нерезидентных ключей идентификатор учетных данных (credential ID) хранится на сервере и предоставляется во время аутентификации. Идентификатор учетных данных представляет собой непрозрачный идентификатор, внутренняя структура которого зависит от реализации: аутентификаторы могут хранить закрытые ключи напрямую, использовать зашифрованную обертку ключей или получать ключи из внутренних секретов. Точный механизм зависит от реализации аутентификатора.
Предупреждение: Если установлено значение "Preferred", пользователь или его устройство могут пропустить проверку пользователя в процессе аутентификации (подробнее читайте в этой статье).
Условный UI (автозаполнение ключей доступа) отображает доступные ключи доступа в выпадающем списке для пользователя, когда у пользователя есть резидентный ключ, зарегистрированный у проверяющей стороны. Это повышает удобство использования ключей доступа, но требует дополнительных усилий по разработке и доступно не для всех комбинаций ОС / браузеров.
Как и обычный вход, Условный UI также использует объекты PublicKeyCredentialRequestOptions и assertion
Условный UI доступен не на всех комбинациях операционных систем и браузеров (пока). Вот обзор текущего охвата браузеров (март 2024 года):
Актуальный обзор можно найти на этом сайте.
Полный минималистичный код для метода Условного UI выглядит следующим образом:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Conditional UI</title> </head> <body> <input type="text" id="username" autocomplete="username webauthn" /> <script> async function passkeyLogin() { try { // получаем параметры запроса (включая вызов) с сервера WebAuthn let options = await WebAuthnClient.getPublicKeyRequestOptions(); const credential = await navigator.credentials.get({ publicKey: options.publicKeyCredentialRequestOptions, mediation: "conditional", }); const userData = await WebAuthnClient.sendSignedChallenge(credential); window.location.href = "/logged-in"; } catch (error) { console.log(error); } } passkeyLogin(); </script> </body> </html>
Условный UI работает только с резидентными ключами / обнаруживаемыми учетными данными.
Рекомендуется предоставить отдельную конечную точку сервера для начала входа в систему через Условный UI.
Клиент должен соответствовать ряду требований:
Во избежание ошибок сервер должен сначала проверить доступность клиента с помощью этой функции:
В реальном трафике проблемы с обнаружением и жизненным циклом часто проявляются как NotAllowedError или AbortError. Используйте руководство по ошибкам WebAuthn для классификации ожидаемых и неожиданных ошибок, включая ошибки нативных менеджеров учетных данных для ключей доступа.
// источник: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredential/isConditionalMediationAvailable#examples // Доступность `window.PublicKeyCredential` означает, что WebAuthn можно использовать. if (window.PublicKeyCredential && PublicKeyCredential.isConditionalMediationAvailable) { // Проверяем доступность условного посредничества (conditional mediation). const isCMA = await PublicKeyCredential.isConditionalMediationAvailable(); if (isCMA) { // Вызываем конечную точку начала аутентификации WebAuthn let options = await WebAuthnClient.getPublicKeyRequestOptions(); const credential = await navigator.credentials.get({ publicKey: options.publicKeyCredentialRequestOptions, mediation: "conditional", }); /* ... */ } }
Поле ввода должно получить HTML-токен автозаполнения (autofill token), который сигнализирует клиенту о необходимости подставить ключи доступа в текущий запрос. Помимо ключей доступа, токены автозаполнения могут быть сопряжены с существующими токенами, например, именами пользователей и паролями:
<label for="name">Username:</label> <input type="text" name="name" autocomplete="username webauthn" /> <label for="password">Password:</label> <input type="password" name="password" autocomplete="current-password webauthn" />
Обязательной или стандартизированной схемы базы данных для серверов WebAuthn не существует. Однако этот пример схемы базы данных может быть использован для хранения необходимой информации и обеспечения всех функций сервера WebAuthn:
Выделенные жирным шрифтом атрибуты обязательны для минимально жизнеспособной реализации, в то время как другие нужны только для дополнительных, но полезных функций.
Отображаемое имя пользователя (user.displayName): Удобное для пользователя, читаемое имя, которое обычно является полным именем пользователя. Оно отображается пользователю, но не используется во время аутентификации.
Имя пользователя (user.name): Уникальное и читаемое имя, которое обычно является адресом электронной почты или логином. Оно может быть показано пользователю, но не используется во время аутентификации.
Идентификатор проверяющей стороны (Relying Party ID, rpID) — это домен, хранящийся внутри ключа доступа, который гарантирует, что ключ доступа работает только для правильного домена (URL-адрес браузера). Во время аутентификации rpID проверяется на соответствие URL-адресу браузера и допускается только в этих двух случаях:
Вот примеры разрешенных и запрещенных комбинаций:
Вот список полезных инструментов и сайтов для внедрения ключей доступа.
chrome://device-log).Чтобы узнать о стратегиях оптимизации пользовательского опыта ключей доступа (UX) за рамками технической реализации, ознакомьтесь с нашими руководствами по лучшим практикам создания ключей доступа и лучшим практикам входа по ключам доступа.
Если вы хотите внедрить ключи доступа всего несколькими строками кода в любое приложение, вы также можете использовать Corbado Complete (для новых приложений) или Corbado Connect (для существующих приложений).
Corbado — это Authentication Intelligence Platform для CIAM-команд, обеспечивающих аутентификацию пользователей в крупных масштабах. Мы показываем то, что не видят логи IDP и общие инструменты аналитики: какие устройства, версии ОС, браузеры и менеджеры учётных данных поддерживают passkey, почему регистрации не превращаются в логины, где сбоит WebAuthn-поток и когда обновление ОС или браузера тихо ломает вход — всё это без замены Okta, Auth0, Ping, Cognito или вашего собственного IDP. Два продукта: Corbado Observe добавляет наблюдаемость для passkey и любых других способов входа. Corbado Connect даёт managed passkey со встроенной аналитикой (рядом с вашим IDP). VicRoads использует passkey для более чем 5 млн пользователей с Corbado (+80 % активации passkey). Поговорить с экспертом по passkey →
Для использования Условного UI требуется проверка поддержки браузером через PublicKeyCredential.isConditionalMediationAvailable() перед началом аутентификации. Поле ввода должно включать HTML-токен autocomplete="username webauthn", а у пользователя должен быть зарегистрирован резидентный ключ (обнаруживаемые учетные данные). Рекомендуется выделить отдельную конечную точку сервера для обработки потока входа через Условный UI.
Как минимум, необходимо хранить Credential ID (идентификатор учетных данных), генерируемый аутентификатором во время регистрации, и User ID (user_id), который возвращается в виде userHandle в объекте утверждения (assertion). Используйте Credential ID для поиска связанной учетной записи пользователя и сравнивайте userHandle для проверки аутентификации. Избегайте использования user.name для сравнения, так как оно может измениться со временем.
Резидентные ключи (обнаруживаемые учетные данные) хранятся на самом аутентификаторе и извлекаются во время аутентификации; это необходимо для работы Условного UI. Нерезидентные ключи хранят идентификатор учетных данных (credential ID) на сервере и отправляют его аутентификатору во время аутентификации. Поле residentKey в authenticatorSelection управляет этим поведением с помощью значений "required", "preferred" или "discouraged".
Поле userVerification контролирует, должен ли аутентификатор проверять пользователя во время входа, принимая значения "required", "preferred" (по умолчанию) или "discouraged". Если установлено значение "preferred", пользователь или его устройство могут полностью пропустить проверку в процессе аутентификации, что потенциально ослабляет безопасность. Установка значения "required" гарантирует, что проверка всегда выполняется до завершения аутентификации.
Посмотрите, как Corbado вписывается во внедрение passkeys и текущий стек аутентификации.
Открыть Console
Похожие статьи
Содержание