Get your free and exclusive +45-page Authentication Analytics Whitepaper
Вернуться к обзору

Полное руководство по ошибкам WebAuthn в рабочей среде (2026)

Узнайте, что означают распространенные ошибки WebAuthn, такие как NotAllowedError, в рабочей среде, и как их классифицировать по типу операции, времени и платформе.

Vincent Delitz
Vincent Delitz

Создано: 9 февраля 2026 г.

Обновлено: 3 июля 2026 г.

Полное руководство по ошибкам WebAuthn в рабочей среде (2026)

Эта страница переведена автоматически. Прочитайте оригинальную версию на английском здесь.

1. Введение#

В рабочей среде ошибки WebAuthn часто вызывают путаницу, поскольку браузеры предоставляют небольшой набор имен DOMException (таких как NotAllowedError), которые могут означать множество базовых причин. Кроме того, подавляющее большинство «ошибок» — часто более 95% в оптимизированных масштабных развертываниях — на самом деле являются ожидаемым поведением (пользователь прервал запрос операционной системы на использование ключа доступа).

Debugger Icon

Экспериментируйте с passkey-флоу в Passkeys Debugger.

Попробовать бесплатно

Важно: Из соображений конфиденциальности браузеры не делают различий между активной отменой пользователем и отсутствием ключа доступа. Однако в некоторых ситуациях и при наличии достаточного контекста, как в веб, так и на нативных платформах, некоторые из этих случаев можно различить с помощью сигналов, таких как время.

Если вам нужны канонические определения этих имен, начните с MDN DOMException. Условия, специфичные для WebAuthn, которые приводят к этим исключениям (и то, что браузеры обязаны обеспечивать), описаны в спецификации W3C Web Authentication.

Если вы относитесь ко всем ошибкам как к «багам», вы будете действовать неправильно:

  • вы загрязните свои метрики ошибок обычными отменами
  • вы пропустите реальные регрессии, скрытые в массе NotAllowedError
  • вы выпустите пользовательский интерфейс, который будет запутывать пользователей, а не помогать им восстановиться

В этой статье мы ответим на следующие вопросы:

  • Что чаще всего означают наиболее распространенные имена ошибок WebAuthn в реальном трафике?
  • Как разделить NotAllowedError на категории, с которыми можно работать (отмена, таймаут, доступность)?
  • Почему одна и та же ошибка означает разные вещи в зависимости от операции (вход с помощью Conditional UI, модальный вход, создание ключа доступа и условное создание)?
  • Какой минимальный контекст вам следует собирать, чтобы сообщение «произошел сбой» превратилось в воспроизводимую проблему?
Ключевые факты
  • NotAllowedError — это поверхностный сигнал, а не первопричина. Это может означать отмену, таймаут, «нет локальных учетных данных» или отсутствие активации пользователем в зависимости от контекста.
  • Тип операции меняет значение. Одно и то же сообщение NotAllowedError означает разные вещи во время входа в систему через Conditional UI, модального входа в систему, создания ключа доступа вручную, условного создания (conditional create) и автоматически запускаемого добавления.
  • Время от начала операции — самый недооцененный сигнал: немедленно (<1s), отмена пользователем (1-15s) и таймаут (30s+) — это принципиально разные категории.
  • AbortError обычно является проблемой жизненного цикла/параллелизма (навигация, повторный рендеринг, несколько одновременных запросов).
  • SecurityError почти всегда связана с конфигурацией/контекстом и редко встречается в зрелых производственных развертываниях.
  • «Имена ошибок браузера» и «отклонения проверки сервером» — это разные уровни. Отслеживайте отклонения сервера как явные коды, а не как общие сбои клиента.
  • Сырые имена ошибок сами по себе не позволяют предпринять никаких действий. Всегда фиксируйте тип операции, время и контекст платформы вместе с error.name, чтобы вы могли разделить ошибки на категории, которые можно фактически исправить.
  • «Окружение» (Environment) — это больше, чем просто браузер + ОС. Чтобы по-настоящему понять ошибки, вам нужно отслеживать полную комбинацию: версию ОС, клиент (браузер/версия приложения), настройки аутентификатора (например, статус iCloud/GPM) и конкретную модель устройства.
  • Ошибки входа — это P1, ошибки создания — P2. В то время как ошибки создания (P2) часто имеют больший объем из-за отказов пользователей, ошибки входа (P1) блокируют доступ и требуют немедленного оповещения.

2. Шпаргалка для рабочей среды#

Если вам нужно просто быстро сопоставить данные для отладки, начните с этой таблицы. Она ориентирована на то, что команды на самом деле видят на дашбордах и в тикетах поддержки.

error.nameЧто это обычно означает в рабочей средеЧто проверить для подтвержденияПервое действие (UX + инженерия)
NotAllowedErrorПользователь закрыл окно, истекло время ожидания или несоответствие доступности, объединенные в одну категорию. Это самая большая группа ошибок в рабочей среде.время до ошибки, появлялся ли QR/гибридный интерфейс, началась ли церемония с реального действия пользователяРассматривать как ожидаемое: восстановить UI + показать резервный вариант
AbortErrorВаше приложение (или браузер) прервало церемониюнавигация/повторный рендеринг во время церемонии; одновременные вызовы WebAuthn; AbortController.abort()Обеспечить один выполняемый запрос; предотвратить смену маршрута; обработать прерывание как обычный поток управления
SecurityErrorКонтекст/политика не разрешеныстратегия origin + RP ID; iframe/встраивание; HTTPS; feature policyИсправить конфигурацию RP ID/origin; проверить политики встраивания; обеспечить безопасный контекст
InvalidStateErrorНесоответствие состояния (часто дублирование регистрации)регистрация или вход; excludeCredentials; существующие учетные данные на аутентификатореРассматривать как «уже зарегистрирован»; скорректировать UX путь; исправить генерацию опций
ConstraintErrorТребования не могут быть удовлетвореныauthenticatorAttachment, userVerification, требования к резидентному ключуОслабить ограничения или предоставить альтернативный путь/резервный вариант. Пример: отсутствие блокировки экрана на Android
DataErrorВходные данные неверного формата/несогласованыкодировка base64url; форматы id/challenge/user handleИсправить кодировку/сериализацию; добавить валидацию при генерации опций
NotSupportedErrorПлатформа/браузер не поддерживает то, что вы запросиливерсия ОС/браузера; допущения при проверке функцийНемедленно перейти к резервному варианту; записать сегмент; избегать показа призывов к действию для ключей доступа в неподдерживаемых средах
UnknownErrorПлатформа/аутентификатор завершились сбоем по общей причиневсплески после обновления ОС; сборка устройства; проблемы с провайдером credential-managerЛояльный к повторным попыткам UX; сбор номеров сборок; исследование всплесков в сегментах

Одна вещь, которую легко упустить: одно и то же error.name может означать совершенно разные вещи в зависимости от типа операции. Держите контекст операции в голове, читая следующие разделы. На практике ошибки создания (регистрации) ключа доступа обычно значительно превышают по количеству ошибки входа — приведенная выше таблица применима к обоим случаям, но большая часть объема приходится на создание.

Далее мы подробнее рассмотрим NotAllowedError, потому что это то, что вы будете видеть чаще всего, и то, что команды чаще всего неверно истолковывают.

3. NotAllowedError: Операция либо прервалась по таймауту, либо не была разрешена#

NotAllowedError часто выглядит так, будто «ключи доступа не сработали», но обычно это платформа сообщает вам, что пользователь не завершил работу с пользовательским интерфейсом ОС. Ключ в том, чтобы разделить ее на категории, с которыми вы сможете работать.

Что вы увидите в консоли браузера:

ИсточникСообщение об ошибке
Chrome, EdgeNotAllowedError: The operation either timed out or was not allowed. See: https://www.w3.org/TR/webauthn-2/#sctn-privacy-considerations-client.
Safari, WebKitNotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.
Safari, WebKitNotAllowedError: This request has been cancelled by the user.
Chrome, EdgeNotAllowedError: The operation is not allowed at this time because the page does not have focus.
Safari, WebKitNotAllowedError: The document is not focused.
FirefoxNotAllowedError: Operation failed.

Все это всплывает как error.name === "NotAllowedError". Сообщение error.message отличается в зависимости от движка браузера и основной причины, но результат один: церемония не завершилась.

Это относится как к входу, так и к созданию ключа доступа. При входе (Conditional UI, модальное окно с или без allowList) NotAllowedError обычно означает, что пользователь не завершил церемонию. При создании ключа доступа та же ошибка возникает по другим причинам: пользователь закрыл диалоговое окно создания (условное создание не сработало, или страница потеряла фокус во время автоматически запускаемого добавления). Тип операции меняет значение ошибки и то, что вам следует с ней делать.

Время часто является недооцененным сигналом. Ошибка менее чем через секунду после клика обычно означает немедленный отказ (среда не может это сделать, документ не в фокусе, отсутствует возможность). Ошибка через несколько секунд — это отмена пользователем (он увидел диалоговое окно и решил не продолжать). Ошибка через 30+ секунд — это таймаут. На нативных платформах время особенно важно: обмен данными с аутентификатором, биометрические запросы и передача данных в менеджер учетных данных имеют характерную продолжительность, которая помогает вам отличить «не сработало» от «пользователь отошел». Вы по-прежнему не можете легко определить, существовал ли ключ доступа.

3.1 Различение с помощью контекста#

Вам не нужен идеальный сигнал. Вам нужно достаточно контекста, чтобы избежать одинакового отношения ко всем NotAllowedError. iOS/Safari уделяется особое внимание ниже, поскольку там есть уникальные ограничения (требования к активации пользователем в более ранних версиях), но по чистому объему ошибок Windows и браузеры на базе Chromium часто генерируют больше NotAllowedError, чем любая другая платформа. Эти сигналы часто позволяют пройти 80% пути:

СигналВероятное значениеЧто делать дальше
Немедленный сбой (<1s)Отказ среды: нет возможности, документ не в фокусе, поверхность условного создания недоступнаПроверить обнаружение функций; убедиться, что документ в фокусе; проверить, поддерживается ли операция на этой платформе
Быстрая отмена (1-3s)Внезапный запрос / нет контекстаИзменить время появления запроса; добавить паузу после отмены
Отмена пользователем (3-15s)Пользователь увидел диалоговое окно и решил не продолжатьОжидаемый UX; восстановить UI + показать резервный вариант
Таймаут (30s+)Церемония прервана по таймауту без действий пользователяКлассифицировать как «не завершено»; подумать, был ли замечен запрос
QR/гибридный UI появляется до сбояНа этом устройстве нет локальных учетных данных. Примечание: надежное определение решений по QR-кодам до того, как они произойдут, требует интеллектуального уровня ключей доступа, который знает, существуют ли пригодные учетные данные на текущем устройстве.Ограничить предложения ключей доступа; сделать «Использовать телефон» явным; уменьшить неожиданные QR-коды
Сосредоточено в iOS/Safari и инициировано без клика/касанияОтсутствует активация пользователемНачинать церемонию с реального жеста пользователя
Во время условного создания или автодобавленияАвтозаполнение недоступно, учетные данные уже существуют, или страница потеряла фокус. Ошибки условного создания могут появляться внезапно и в больших объемах при запуске функции, что делает это одним из крупнейших источников ошибок за одну ночь.См. условное создание; проверить состояние видимости документа; использовать getClientCapabilities() для проверки поддержки conditionalCreate перед попыткой вызова

Вот почему NotAllowedError редко должна быть видимой пользователю. Это не то сообщение, на которое пользователь может как-то отреагировать.

Разделение по контексту также является тем местом, где показатели успешности разделяются наиболее резко. Анализ успешности аутентификации с помощью ключей доступа Corbado Passkey Benchmark 2026 оценивает завершение в первом квартале 2026 года на уровне 55–95% для потоков с неизвестным устройством (identifier-first) в сравнении с 95–99% для возвратов с известных устройств в масштабных развертываниях B2C. Веб-версия iOS (identifier-first) достигает 85–95% завершения (% CDA 0–5%), веб-версия Android — 70–85% (% CDA 5–10%) и веб-версия macOS — 70–85% (% CDA 10–15%), в то время как веб-версия Windows находится на уровне 45–60% завершения (identifier-first) с % CDA 55–65% на Windows 11 и 40–55% на Windows 10. Чтение объема NotAllowedError без разделения контекстов известных и неизвестных устройств смешивает два фундаментально разных режима успешности.

Один нюанс, который имеет значение на практике: некоторые агенты пользователя могут выводить таймауты как TimeoutError, но многие команды по-прежнему видят, что на дашбордах таймауты сводятся к NotAllowedError. В любом случае рассматривайте таймауты как «церемония не завершена» и классифицируйте, используя время плюс контекст.

3.2 Обработка UX: сделайте отмену обычным выходом#

Когда окно ОС закрывается или истекает время ожидания, ваш UI должен немедленно восстановиться и отреагировать изящно. Практический набор правил:

  • восстановить UI входа (никаких бесконечно крутящихся спиннеров)
  • сохранить состояние идентификатора (не заставлять вводить заново)
  • показать видимый резервный вариант на том же экране
  • избегать пугающих баннеров для ожидаемых результатов

Помимо базовых правил:

  • Рассматривайте первую отмену как нормальную и предложите повторить попытку со спокойным объяснением. Только после второй отмены следует предлагать резервные варианты (см. резервные варианты и восстановление ключей доступа).
  • Разрешите до трех запросов на создание перед паузой, чтобы удивленные пользователи получили второй шанс (см. лучшие практики создания ключей доступа).
  • Разделяйте счетчики ошибок между созданием и входом, чтобы сравнивать подобное с подобным.
  • Сегментируйте процент ошибок по ОС, браузеру и устройству, чтобы вы могли обнаружить, где на самом деле возникают трудности (см. лучшие практики входа с помощью ключей доступа).

Если ваших «отмен» действительно много, следующим шагом будет устранение их первопричин: время запросов, неожиданные QR-коды и низкая доступность.

3.3 Инженерные исправления, снижающие NotAllowedError#

Начните с изменений, которые быстро улучшают метрики:

  • Исправьте время запросов и активацию пользователем (особенно на iOS/Safari): события WebAuthn, активируемые пользователем в Safari.
  • Уменьшите количество сюрпризов с QR/гибридными интерфейсами: почему процессы использования ключей доступа показывают QR-коды и пользователи отказываются.
  • Ограничивайте предложения, чтобы ключи доступа показывались тогда, когда они скорее всего сработают: предлагайте ключи доступа только тогда, когда это вероятно увенчается успехом.
  • Используйте паттерны, избегающие запросов, когда нет локальных учетных данных: немедленное посредничество WebAuthn.
  • Обрабатывайте нестабильность сети: Сетевые ошибки во время проверки часто проявляются как общие сбои на стороне клиента. Реализуйте автономную очередь для ваших журналов телеметрии, чтобы не потерять данные об ошибках, когда связь пользователя обрывается во время церемонии.
  • Ограничивайте церемонии с помощью API обнаружения, чтобы сбои среды не увеличивали вашу корзину NotAllowedError. Начните с isUVPAA() в качестве самого базового ограничения, затем используйте getClientCapabilities() для более точных проверок (условное создание, условное получение, гибридный транспорт, платформенный аутентификатор). Имейте в виду, что API обнаружения могут сломаться при обновлениях ОС: в iOS 26.2 был выпущен баг WebKit, при котором isUVPAA() возвращает false во всех браузерах на базе WKWebView, хотя ключи доступа работают нормально, вызывая внезапные всплески NotAllowedError у 10-25% пользователей iOS (см. исправление обнаружения ключей доступа с помощью getClientCapabilities()).

3.4 Примечание о развитии имен ошибок#

Имена ошибок — это движущаяся цель. Существуют текущие предложения по добавлению более детальных ошибок WebAuthn (например, чтобы отделить «нет доступных учетных данных» от «пользователь отменил»). По состоянию на февраль 2026 года это не реализовано ни в одном браузере, поэтому по-прежнему стоит создавать собственные корзины причин на основе контекста и времени. Если вы хотите отслеживать эту работу, см. WebAuthn issue #2062 и объяснение "Новые коды ошибок".

Остальные имена ошибок встречаются реже, но их все равно стоит понимать, когда они появляются.

4. AbortError: Операция была прервана#

AbortError редко встречается в больших объемах по сравнению с NotAllowedError, но когда она появляется, она очень диагностична: обычно это означает, что церемония не была завершена, потому что ваше приложение сделало запрос недействительным — произошла навигация, изменилось состояние или начался второй запрос.

Что вы увидите в консоли браузера:

ИсточникСообщение об ошибке
Chrome, EdgeAbortError: The operation was aborted.
Chrome, EdgeAbortError: Aborted by AbortSignal.
FirefoxAbortError: signal is aborted without reason
FirefoxAbortError: Operation timed out.
Safari, WebKitAbortError: The user aborted a request.
ChromeAbortError: CredentialContainer request is not allowed.

Общие причины в рабочей среде включают:

  • несколько одновременных вызовов WebAuthn (два конфликтующих запроса)
  • изменение маршрута/повторный рендеринг во время выполняемой церемонии
  • вызов AbortController.abort() во время повторных попыток или очистки состояния

Чтобы исправить это, сосредоточьтесь на том, чтобы сделать церемонию «критической секцией»:

  • разрешайте только один выполняемый запрос за раз
  • блокируйте навигацию во время церемонии (или чисто отменяйте ее и восстанавливайте UI)
  • рассматривайте прерывание как ожидаемый поток управления: покажите кнопку повтора и резервный метод

Если вы видите AbortError, сконцентрированную во встроенных поверхностях или многодоменных приложениях, следующая категория для проверки — это SecurityError.

5. SecurityError: WebAuthn не поддерживается на сайтах с ошибками сертификатов TLS#

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

Общие причины включают:

  • Несоответствие RP ID / origin (многодоменные установки)
  • ограничения встраивания cross-origin (iframe)
  • небезопасный контекст (не HTTPS) или заблокированные разрешения/политики
  • .well-known/webauthn или .well-known/assetlinks.json неправильно настроены, отсутствуют или временно недоступны. Проблемы с сетью во время критического окна, когда браузер запрашивает эти файлы, приведут к сбоям. Распространенное слепое пятно: если ваша домашняя страница недоступна из-за обслуживания, файлы well-known также не в сети, что ломает церемонии с ключами доступа во всех relying parties, которые от них зависят.

Что вы увидите в консоли браузера:

ИсточникСообщение об ошибке
Chrome, EdgeSecurityError: WebAuthn is not supported on sites with TLS certificate errors.
Любой браузерSecurityError: The relying party ID is not a registrable domain suffix of, nor equal to the current origin's effective domain.
Chrome (iframe)SecurityError: The 'publickey-credentials-create' feature is not enabled in this document.

В рабочей среде SecurityError редки — они почти всегда выявляются во время интеграционного тестирования. Когда они появляются, ошибка сертификата TLS является наиболее частой причиной.

Самый быстрый цикл отладки:

  • зарегистрируйте входные данные origin и RP ID, которые вы использовали
  • воспроизведите в том же контексте (верхний уровень или iframe, рабочий домен или staging)
  • если вы встраиваете вход, убедитесь, что политика разрешений настроена (например, publickey-credentials-create / publickey-credentials-get): MDN Permissions-Policy
  • проверьте вашу стратегию доменов (см. связанные origins)
  • если вы используете iframe, проверьте политики функций (см. ключи доступа в iframe)

Как только SecurityError обработана, следующая группа, к которой следует отнестись серьезно, — это набор ошибок, которые часто указывают на баги реализации: InvalidStateError, ConstraintError и DataError.

PasskeysCheatsheet Icon

Шпаргалка по Passkeys. Практические рекомендации, шаблоны внедрения и KPI для программ passkeys.

Получить шпаргалку

6. InvalidStateError, ConstraintError, DataError: рассматривайте как баги реализации#

Эти ошибки должны быть редкими в зрелой реализации ключей доступа. Когда они появляются, это обычно указывает на то, что генерация опций неверна для сегмента или что поток находится в неправильном состоянии.

6.1 InvalidStateError: "учетные данные уже зарегистрированы для этой проверяющей стороны"#

Что вы увидите в консоли браузера:

ИсточникСообщение об ошибке
Safari, WebKitInvalidStateError: The user attempted to register an authenticator that contains one of the credentials already registered with the relying party.
Chrome, EdgeInvalidStateError: At least one credential matches an entry of the excludeCredentials list in the platform attached authenticator.
Chrome, EdgeInvalidStateError: A request is already pending.
FirefoxInvalidStateError: An attempt was made to use an object that is not, or is no longer, usable

Типичные значения:

  • регистрация: вы попытались создать учетные данные, которые уже существуют (дубликат)
  • вход: менее распространено; часто означает, что поток/состояние непоследовательно для платформы

Практическая обработка:

  • если это происходит при ручной регистрации, рассматривайте это как «уже зарегистрирован» и маршрутизируйте соответствующим образом
  • убедитесь, что excludeCredentials содержит список всех существующих идентификаторов учетных данных для пользователя, чтобы аутентификатор мог обнаружить дубликаты (см. excludeCredentials)
  • во время условного создания InvalidStateError является ожидаемой и должна молча игнорироваться: это означает, что ключ доступа уже существует у провайдера. То же самое относится к NotAllowedError и AbortError во время условного создания (см. условное создание в Chrome)

6.2 ConstraintError#

Типичное значение: аутентификатор не может удовлетворить ваши запрошенные ограничения.

Общие триггеры:

  • отсутствие блокировки экрана устройства (особенно на Android): платформа требует биометрической или PIN проверки, но на устройстве не настроен экран блокировки
  • слишком строгие authenticatorAttachment или предположения о резидентном ключе
  • жесткие требования userVerification в сегментах, где они недоступны

Исправление: ослабьте ограничения (где это приемлемо) или предоставьте альтернативный путь. В случае отсутствия блокировки экрана рассмотрите возможность обнаружения этого условия и направления пользователей, а не молчаливого сбоя (Android).

6.3 DataError#

Типичное значение: входные данные имеют неверный формат или непоследовательны.

Общие триггеры:

  • ошибки кодирования (base64 вместо base64url)
  • недействительные форматы id учетных данных / challenge

Исправление: проверяйте и нормализуйте входные данные на границе, где вы генерируете параметры WebAuthn. На практике DataError фактически отсутствует в зрелых производственных системах — если генерация ваших параметров протестирована, вы не увидите это на дашбордах.

Если эти ошибки находятся под контролем, следующий вопрос — это покрытие: происходят ли сбои у пользователей из-за того, что окружение не может выполнить WebAuthn так, как вы ожидаете?

7. NotSupportedError: Агент пользователя не поддерживает учетные данные с открытым ключом#

NotSupportedError — это сигнал о покрытии, а не о надежности. Обычно это означает, что сегмент не может выполнить то, что вы просили (ОС/браузер слишком старые, отсутствует возможность, функция не включена).

Что вы увидите в консоли браузера:

ИсточникСообщение об ошибке
Chrome, EdgeNotSupportedError: The user agent does not support public key credentials.
FirefoxNotSupportedError: Resident credentials or empty 'allowCredentials' lists are not supported.
Chrome, Edge, FirefoxTypeError: PublicKeyCredential.parseCreationOptionsFromJSON is not a function
Chrome, Edge, FirefoxTypeError: PublicKeyCredential.parseRequestOptionsFromJSON is not a function
Chrome, Edge, FirefoxTypeError: credential.toJSON is not a function
SafariTypeError: Can only call PublicKeyCredential.toJSON on instances of PublicKeyCredential

Первые два — это подлинные NotSupportedError DOMExceptions. Записи TypeError технически являются другим типом исключения, но представляют тот же класс проблем: браузер или среда не поддерживают то, что вы запросили. Семейство JSON сериализации TypeError на практике встречается гораздо чаще, чем само исключение NotSupportedError (см. ниже).

Общие причины включают:

  • старые версии браузеров/ОС, которые не поддерживают базовый WebAuthn
  • запрос функций WebAuthn, недоступных на этой платформе
  • попытка выполнить платформо-специфичные потоки на неподдерживаемых устройствах

Семейство сериализации JSON является крупнейшим источником сбоев класса NotSupportedError в рабочей среде. Технически они проявляются как TypeError (отсутствующий метод), а не как DOMException, но именно здесь вы с ними столкнетесь. Две разные первопричины:

  1. Браузер не поддерживает методы сериализации JSON WebAuthn. В браузере есть navigator.credentials, но нет PublicKeyCredential.parseCreationOptionsFromJSON / parseRequestOptionsFromJSON. На это приходится примерно 90% этого семейства ошибок, сосредоточенных в старых версиях Safari и Chrome. Если ваша клиентская библиотека зависит от этих методов без резервного варианта, это создает значительный объем ошибок.
  2. Расширения менеджеров паролей ломают .toJSON(). Расширения, такие как Bitwarden, LastPass или 1Password, могут перехватить церемонию и вернуть объект, который выглядит как учетные данные, но не является реальным экземпляром PublicKeyCredential. Вызов .toJSON() для него либо вызывает исключение, либо возвращает undefined, либо объект вообще является null. Это составляет примерно 10% семейства, но их особенно сложно отлаживать, потому что сообщения об ошибках различаются в зависимости от браузера (Safari: "Can only call on instances of PublicKeyCredential"; Firefox: "does not implement interface PublicKeyCredential").

Обработка должна быть прямой и быстрой:

  • немедленно переходите к резервному паролю/OTP
  • запишите сегмент, чтобы можно было количественно оценить пробелы в покрытии
  • избегайте показа призывов к действию для ключей доступа в сегментах, которые постоянно будут давать сбой

Если с покрытием всё в порядке, но сбои всё еще происходят в конкретных сегментах, возможно, вы имеете дело с проблемами на уровне платформы, проявляющимися как UnknownError.

8. UnknownError: Произошла неизвестная ошибка при общении с менеджером учетных данных#

UnknownError — это универсальная категория для сбоев аутентификатора/ОС, которые не вписываются в другие категории. Это часто временно, но также может возрастать после обновлений ОС.

Что вы увидите в консоли браузера:

ИсточникСообщение об ошибке
Chrome (Android)UnknownError: An unknown error occurred while talking to the credential manager.
Любой браузерUnknownError: The operation failed for an unknown transient reason.
Любой браузерUnknownError: Either the device has received unexpected request data, or the device has been reconfigured since the request was made.
Любой браузерUnknownError: Something went wrong.
Chrome (LastPass)TypeError: Cannot use 'in' operator to search for 'type' in null
Safari (LastPass)TypeError: null is not an Object. (evaluating 'key in input')
Chrome (Bitwarden)FallbackRequested

Практическая обработка:

  • используйте лояльный к повторным попыткам UX (не "вините пользователя")
  • собирайте номера ОС/сборок и контекст менеджера/провайдера учетных данных, где это возможно
  • следите за всплесками в конкретных сегментах после обновлений ОС

Один нишевый источник ошибок, который не вписывается ни в одну категорию DOMException: расширения браузера для управления паролями (такие как Bitwarden, LastPass, 1Password и другие) могут перехватывать вызовы API WebAuthn и возвращать нестандартные ответы. Несмотря на то, что их объем невелик по сравнению с отменами пользователей, их стоит отслеживать, поскольку они стабильно влияют на определенные сегменты пользователей, а симптомы запутывают: отсутствие методов в возвращаемом объекте учетных данных, неожиданные типы ошибок или некорректные ответы, которые не соответствуют ни одной документированной ошибке WebAuthn. Часто они появляются как UnknownError или как неклассифицированные исключения. Если вы видите всплески ошибок, сосредоточенные в конкретных браузерах без объяснения на уровне ОС, проверьте, не задействовано ли расширение менеджера учетных данных.

До сих пор мы говорили об именах ошибок в веб-браузерах. Но если вы также поставляете нативные приложения, ландшафт ошибок другой — и в некоторых отношениях значительно лучше.

9. Несколько слов о нативных приложениях (iOS и Android)#

Всё вышеперечисленное касается веб-браузеров. Нативные приложения — iOS с фреймворком ASAuthorization, Android с Credential Manager — имеют те же базовые категории ошибок, но отличаются важными деталями:

  1. «Нет учетных данных» — это отдельный сигнал. В вебе браузеры объединяют «нет доступных учетных данных» и «отменено пользователем» в одно и то же NotAllowedError из соображений конфиденциальности. На нативных платформах использование preferImmediatelyAvailableCredentials на iOS (ASAuthorizationController) или setPreferImmediatelyAvailableCredentials(true) на Android (GetCredentialRequest) сообщает ОС показывать только учетные данные, которые уже есть на устройстве, и немедленно завершаться сбоем, если их нет. Это дает чистый результат «нет учетных данных», который не может дать веб.

  2. Статус провайдера учетных данных виден. Нативные платформы при некоторых условиях могут сообщить вам, когда провайдер учетных данных (Google Password Manager, iCloud Keychain, 1Password и т. д.) не установлен, не настроен или не установлен по умолчанию, и отреагировать на это. В вебе эта информация скрыта за непрозрачными сообщениями NotAllowedError.

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

9.1 iOS (фреймворк ASAuthorization)#

iOS передает ошибки ключей доступа через фреймворк ASAuthorization. Все ошибки приходят в callback делегата authorizationController(controller:didCompleteWithError:) как объекты NSError.

Классифицируйте по домену + коду, а не по строке сообщения. Основной домен ошибки — com.apple.AuthenticationServices.AuthorizationError (ASAuthorizationError.errorDomain). Приведите ошибку с помощью let nsError = error as NSError и сопоставляйте по .domain и .code. Никогда не сопоставляйте по .localizedDescription в рабочей среде — сообщения Apple локализуются на более чем 30 языков и могут меняться в разных версиях ОС. Строки сообщений, перечисленные ниже, полезны для распознавания ошибок в журналах, но они не являются критериями классификации.

Публичные коды ASAuthorizationError:

КодИмяСЧто это значит
1000UnknowniOS 13Не должно появляться в рабочей среде. Общая категория.
1001CancelediOS 13Пользователь закрыл окно ключей доступа. Самая частая ошибка в целом — эквивалент NotAllowedError. Чистый сигнал с пустым userInfo и без базовой ошибки.
1002InvalidResponseiOS 13Повреждение на уровне фреймворка. Редко встречается на практике.
1003NotHandlediOS 13Ни один провайдер не обработал запрос. Проверьте entitlements и конфигурацию провайдера учетных данных.
1004FailediOS 13Общий сбой. localizedDescription содержит реальную причину (например, "Application with identifier X is not associated with domain Y"). userInfo может содержать строку FailureReason, но NSUnderlyingErrorKey не всегда заполнен — сбои связи с доменом возвращают nil для базовой ошибки.
1005NotInteractiveiOS 15Нет доступных учетных данных при использовании preferImmediatelyAvailableCredentials. Это чистый сигнал "не найдено" — iOS-эквивалент "на этом устройстве нет ключа доступа." Интерфейс не был показан.
1006MatchedExcludedCredentialiOS 18Ключ доступа уже существует для этого RP на этом устройстве. Чистый сигнал для обнаружения дубликатов — пустой userInfo, нет NSUnderlyingErrorKey. Классификация работает без сопоставления строк.
1007CredentialImportiOS 18.2Не удалось импортировать учетные данные.
1008CredentialExportiOS 18.2Не удалось экспортировать учетные данные.
1009PreferSignInWithAppleiOS 26Пользователь предпочитает Sign in with Apple вместо ключа доступа. Новое в iOS 26.
1010DeviceNotConfiguredForPasskeyCreationiOS 26На устройстве отсутствует код доступа или конфигурация iCloud Keychain. Известный баг симулятора iOS 26: возвращает 1010, даже когда конфигурация верна (не воспроизводится на физических устройствах).

Самое важное различие для рабочей среды: начиная с iOS 18, дублирующиеся учетные данные возвращают свой собственный код ошибки 1006 (MatchedExcludedCredential). На iOS 17 и более ранних версиях дублирующиеся учетные данные были скрыты внутри кода 1004 (Failed). В iOS 18+ различие носит структурный характер (разный код ошибки), а не текстовый.

Общие ошибки времени выполнения (справочник уровня журнала):

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

Сообщение (Английская локаль)Базовый кодПримечания
Application with identifier <TeamID.BundleID> is not associated with domain X1004 (Failed)Разрешение Associated Domains приложения не совпадает с проверяющей стороной. Исправьте файл apple-app-site-association на вашем сервере.
Couldn't communicate with a helper application.1004 (Failed)Расширение провайдера учетных данных не ответило. Временная ошибка — уместна повторная попытка.
Request already in progress for specified application identifier.1004 (Failed)Был отправлен дублирующийся запрос ASAuthorization, пока один находился в ожидании. Состояние гонки в приложении.
Stolen Device Protection is enabled and biometry is required.1004 (Failed)Защита украденного устройства в iOS 17+ блокирует биометрическую аутентификацию в незнакомых местах. Нельзя исправить со стороны разработчика, но стоит сообщить об этом пользователю.
(AuthenticationServicesCore.ASCABLEClient.ClientError error 2.)Отдельный доменСбой рукопожатия Bluetooth при кросс-устройственной аутентификации (гибридной/CABLE).
(AuthenticationServicesCore.ASCABLEClient.ClientError error 3.)Отдельный доменСбой подключения Bluetooth при кросс-устройственной аутентификации.

Локализованные сообщения «нет учетных данных» (код 1005):

Когда установлено preferImmediatelyAvailableCredentials и ключ доступа не существует, iOS возвращает код 1005 (NotInteractive) с локализованным сообщением на языке устройства пользователя. Это уникально для нативных приложений — веб-браузеры никогда не выдают этот сигнал. Сообщение всегда начинается с The operation couldn't be completed. (Операция не может быть завершена.), за которым следует локализованный текст:

ЯзыкСообщение
Китайский (Упрощенный)没有可用于登录的凭证。
ВьетнамскийKhông có sẵn thông tin để đăng nhập.
Арабскийلا تتوفر بيانات اعتماد لتسجيل الدخول.
ИспанскийNo hay ninguna credencial disponible para iniciar sesión.
Китайский (Традиционный)沒有可用於登入的憑證。
Корейский로그인을 위한 자격 증명이 없습니다.
Французский (Канада)Aucun identifiant disponible pour la connexion.
Португальский (Бразилия)Nenhuma credencial disponível para login.
Французский (Франция)Aucune information d'identification n'est disponible pour procéder à la connexion.
Тайскийไม่มีข้อมูลประจำตัวสำหรับเข้าสู่ระบบ
ИтальянскийNon ci sono credenziali disponibili per l'accesso.
НидерландскийGeen inloggegevens beschikbaar.
Японскийログイン用の資格情報がありません。
ТурецкийOturum açmak için kullanılabilecek kimlik bilgisi yok.

На устройствах с английской локалью обычно отсутствие учетных данных разрешается на уровне API до того, как фреймворк ASAuthorization вернет локализованную ошибку, поэтому выше нет английского варианта. Программно всегда сопоставляйте код 1005, а не парсите эти строки.

9.2 Android (Credential Manager API)#

Android передает ошибки ключей доступа через Credential Manager API (androidx.credentials). Сообщения об ошибках включают основное сообщение и часто cause с дополнительными деталями. По сравнению с iOS, Android предоставляет более структурированные типы ошибок и более явные причины для проблем конфигурации.

Отмена пользователем и обнаружение учетных данных:

ОшибкаПримечания
User cancelled the operationПользователь закрыл запрос ключа доступа. Эквивалент NotAllowedError. Примечание: Credential Manager также возвращает User canceled the request (написание США) из другого пути кода — оба идентичны.
Excluded credential matches existing credentialКлюч доступа уже существует для этого ID учетных данных. Эквивалент InvalidStateError. В отличие от iOS, сообщение отличается от отмены пользователем.
No create options available.Ни один подходящий провайдер учетных данных не может обработать запрос на создание. Обычно означает, что сервисы Google Play устарели или ни один провайдер учетных данных не поддерживает создание ключей доступа.

Ошибки конфигурации и безопасности:

ОшибкаПримечания
Passkeys not supported for this appDigital Asset Links (assetlinks.json) отсутствует или не содержит отпечаток сертификата подписи приложения. Эквивалент SecurityError.
Https failed: respCode=301, url=https://<domain>/.well-known/assetlinks.jsonФайл assetlinks.json возвращает редирект вместо HTTP 200. Android требует наличия файла по точному URL без редиректов.
The incoming request cannot be validatedCredential Manager не может проверить запрос на соответствие Digital Asset Links.
RP ID cannot be validated.Идентификатор проверяющей стороны (RP ID) в параметрах WebAuthn не соответствует assetlinks.json.
Screen lock is missing.На устройстве не настроен PIN, графический ключ или биометрия. Ключи доступа требуют проверки пользователя. Эквивалент ConstraintError.
Cannot find an eligible account.Ни один аккаунт Google на устройстве не подходит для создания ключа доступа (редко, обычно пользовательские корпоративные настройки).

Ошибки платформы и аутентификатора:

ОшибкаПримечания
Unsuccessful result from folsom activity.Внутренний сбой сервисов Google Play. "Folsom" — это компонент GMS для операций с ключами доступа. Временная ошибка — уместна повторная попытка.
Can't find the proper key to decrypt the private key from WebauthnCredentialSpecifics.Синхронизированный ключ доступа существует, но устройство не может расшифровать его закрытый ключ. Состояние синхронизации Google Password Manager несогласованно — учетные данные были синхронизированы с другого устройства, но ключ расшифровки недоступен. Нельзя исправить со стороны разработчиков.
Operation was interrupted (cause: The UI was interrupted - please try again.)Пользовательский интерфейс Credential Manager был прерван другой активностью (входящий вызов, поворот экрана, приложение свернуто). Эквивалент AbortError.
Unknown credential errorУниверсальная категория, когда не применяется ни один конкретный тип ошибки. Обычно временная.
timeout (cause: Canceled)Время ожидания операции Credential Manager истекло до того, как пользователь завершил биометрическую проверку.

10. Собираем все вместе: таксономия ошибок#

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

Ключевой вывод: необработанное error.name имеет смысл только тогда, когда вы знаете, какой уровень окружения его произвел, какая операция выполнялась и была ли ошибка ожидаемой или непредвиденной. Разделы ниже описывают, что следует логировать и как на это реагировать.

11. Что регистрировать, чтобы ошибки можно было отлаживать#

Большую часть классификации ошибок, описанной в этой статье, можно выполнить только с помощью сигналов на стороне клиента. Фронтенд-SDK наблюдаемости собирает достаточно контекста, чтобы классифицировать подавляющее большинство ошибок WebAuthn. Именно так архитектурно устроен SDK наблюдаемости Corbado: слой на стороне клиента обрабатывает атрибуцию ошибок, время, контекст операции и обнаружение платформы. Логирование на стороне сервера добавляет второй уровень для сбоев, которые может видеть только бэкенд.

Ключевое требование: каждая попытка должна быть объединяема от начала до конца. Общий идентификатор корреляции (например, auth_flow_id) связывает контекст на стороне клиента с результатом проверки на сервере.

11.1 Сигналы на стороне клиента (Frontend SDK)#

СигналПочему это важно
error.name + нормализованная категория причиныСырая ошибка браузера + ваша классификация
Тип операцииConditional UI, модальный вход, создание вручную, условное создание, автодобавление. CDA (кросс-устройственная аутентификация) — это отдельный сложный зверь.
Полный контекст окруженияОС + версия, браузер + версия, Марка/модель оборудования, Настройки аутентификатора (например, GPM включен?)
Контекст аутентификатора / менеджера учетных данныхПоломки расширений и провайдеров
Время до ошибки с начала операцииНемедленный отказ (<1s) против отмены пользователем (1-15s) против таймаута (30s+)
Сеть / статус подключенияСетевые ошибки часто проявляются как ошибки клиента. Отслеживайте, был ли пользователь офлайн, и ставьте в очередь логи для отправки при восстановлении связи.
Появлялся ли QR/гибридный UIЛокальный сбой против сбоя кросс-устройства
Идентификатор корреляции (auth_flow_id)Объединение с логами сервера

11.2 Сигналы на стороне сервера (Backend Verification)#

Сбои проверки на сервере происходят после того, как браузер возвращает учетные данные и подписанный challenge. Они должны быть структурированными ошибками с явными кодами, а не смешиваться в одной корзине с именами клиентских DOMException. См.: реализация сервера WebAuthn.

СигналПочему это важно
Несоответствие challenge / challenge с истекшим сроком действияПроблемы со временем сеанса или атаки повторного воспроизведения
Несоответствие Origin / RP IDОшибки конфигурации нескольких доменов
Неверная подпись / учетные данные не найденыУдаленные или поврежденные учетные данные. Частый случай: вход с Conditional UI с помощью ключа доступа, который пользователь уже удалил на стороне сервера. Используйте Signal API, чтобы синхронизировать списки учетных данных клиента и сервера.
Несоответствие User handleПроблемы с сопоставлением учетных записей
Идентификатор корреляции (auth_flow_id)Объединение с контекстом на стороне клиента

Если вам нужна полная модель воронки (отсевы по шагам и конверсия между шагами), см.: телеметрия ключей доступа для понимания отсевов.

Substack Icon

Подпишитесь на наш Passkeys Substack, чтобы получать новости.

Подписаться

При наличии этих данных вывод становится простым: большинство «ошибок» становятся либо исправлениями UX, либо исправлениями покрытия, либо исправлениями конфигурации. Но создание и поддержание этой классификации собственными силами — это значительная постоянная работа.

12. Больше, чем имена ошибок: как Corbado превращает сырые ошибки в практичные сигналы#

Приведенный выше контрольный список логирования собирает необработанные сигналы. В рабочей среде в больших масштабах одного error.name недостаточно. Создание этой классификации самостоятельно — это значительная постоянная работа: сообщения об ошибках меняются с каждым выпуском браузера и ОС, провайдеры менеджеров паролей выпускают обновления, которые изменяют поведение церемоний, а новые сигнатуры ошибок появляются с запуском каждой функции.

12.1 Почему одного error.name недостаточно#

Одно и то же сообщение NotAllowedError может означать шесть разных вещей в зависимости от трех измерений, которые браузеры не разделяют для вас:

ИзмерениеЧто дают вам браузерыЧто вам на самом деле нужноПример
Контекст операцииNotAllowedErrorБыл ли это Conditional UI, модальный вход, создание вручную, условное создание или автодобавление?Android возвращает одну и ту же «неизвестную ошибку» при закрытии входа (ожидаемо) и сбое создания (непредвиденно)
ВремяНет данных о продолжительностиНемедленный отказ (<1s) против отмены пользователем (1-15s) против таймаута (30s+)200 мс = отказ среды; 5с = пользователь увидел диалоговое окно и отменил; 35с = таймаут
Платформа + аутентификаторОбщее error.nameОС, браузер, версия, менеджер учетных данных для каждой ошибки«пользователь закрыл диалоговое окно» в Chrome и «автозаполнение недоступно» в Safari оба появляются как NotAllowedError

12.2 Что собирает SDK наблюдаемости Corbado#

Именно для решения этой проблемы создан SDK наблюдаемости Corbado. Это легковесная фронтенд-интеграция, которая работает поверх вашей существующей реализации ключей доступа, с любым сервером WebAuthn и любым IDP, и автоматически классифицирует каждую ошибку WebAuthn по всем трем измерениям:

ВозможностьЧто она делает
Атрибуция ошибокФиксирует ОС, версию ОС, браузер, версию браузера и аутентификатор при каждой попытке церемонии
Режим операцииСвязывает каждую ошибку с конкретной операцией (Conditional UI, модальный вход, создание вручную, условное создание, автодобавление), поэтому одно и то же сообщение NotAllowedError разрешается в разные первопричины
Время от начала действияЗаписывает продолжительность от начала церемонии, чтобы без угадывания различать немедленные отказы, отмены пользователем и таймауты
Интеллектуальная классификация ошибокСопоставляет полный контекст ошибки (а не только имя), нормализуя различные окружения (ОС, оборудование, настройки). Определяет приоритет различных групп ошибок, таких как CDA или локальные, и отличает Ожидаемые (Отмена пользователем) от Непредвиденных (Сбой системы).
Фрагментация менеджеров паролейОбнаруживает, когда расширения менеджеров учетных данных (Bitwarden, 1Password, LastPass) перехватывают церемонии и возвращают нестандартные ответы, отделяя сбои, вызванные расширением, от сбоев платформы

Это уровень Observe: видимость того, что происходит, без изменения вашей реализации.

12.3 Два пути отладки: сверху вниз и снизу вверх#

Консоль управления Corbado поддерживает два пути расследования:

Сверху вниз (от дашборда к первопричине):

  1. Мониторинг двух разных типов аномалий:
    • Увеличение количества ожидаемых ошибок (Дрейф базовой линии): Увеличилось ли постепенно количество «отмен пользователем» в определенном окружении (например, iOS 18.2 на iPhone 15)? Это часто указывает на трудности UX, внесенные обновлением ОС.
    • Увеличение количества непредвиденных ошибок (Всплески): Совершенно новая ошибка или внезапный скачок сбоев. Это обычно указывает на критическое изменение (внутреннее обновление стека IDP) или регрессию в новой версии браузера.
  2. Расстановка приоритетов по влиянию:
    • P1: Проблемы со входом. Если показатели успешности входа падают, подавайте сигнал немедленно.
    • P2: Проблемы с созданием. Отслеживайте тенденции, но не стоит будить инженеров из-за всплесков «отмен пользователем» в потоках создания.
  3. Детализация окружения: Используйте детализированные измерения (оборудование, настройки аутентификации), чтобы определить, является ли проблема глобальной или специфичной для «устройств Samsung с Android 14».
  4. Смягчение последствий: Если обнаружен критический всплеск, подготовьте Kill Switch (рубильник). Автоматически или вручную отключите ключи доступа для этого конкретного окружения и вернитесь к OTP/паролям, чтобы сохранить процент входов, пока вы разбираетесь в проблеме.

Снизу вверх (от шаблонов ошибок к влиянию):

  1. Начните с представления классификации ошибок. Просмотрите классифицированные шаблоны ошибок и их объемы.
  2. Уточняйте сопоставление ошибок по мере появления новых шаблонов (например, новая версия браузера выдает другое сообщение об ошибке).
  3. Ошибки сопоставляются с изменениями KPI и отображаются в виде аннотаций на дашбордах, поэтому всплеск определенного шаблона ошибок автоматически связывается с метрикой, на которую он повлиял.

Оба пути сходятся: сверху вниз сообщает вам, что что-то не так, снизу вверх сообщает вам почему. AI Analytics Assistant связывает оба подхода, позволяя задавать вопросы естественным языком об ошибках и метриках внедрения.

Команды, которые хотят действовать на основе этих сигналов, могут перейти к уровню Adopt, который добавляет интеллект ключей доступа для автоматического ограничения церемоний, оптимизации запросов на регистрацию и восстановления сломанных состояний ключей доступа. Для регулируемых сред или гипермасштабных развертываний Enterprise добавляет однотенантный хостинг, интеграцию SIEM и конфигурацию, соответствующую PSD2.

Enterprise Icon

Получите бесплатный whitepaper по passkeys для enterprise.

Получить бесплатно

13. Заключение#

Имена ошибок WebAuthn — это не приговор. Это подсказки, и они становятся полезными только тогда, когда вы связываете их с типом операции, временем и контекстом платформы.

  • Что означают наиболее распространенные имена ошибок WebAuthn в рабочей среде? В основном они сводятся к небольшому набору уровней: контроль потока пользователем (NotAllowedError), жизненный цикл приложения/параллелизм (AbortError), контекст безопасности/конфигурации (SecurityError) или баги опций/состояния (InvalidStateError, ConstraintError, DataError). Подавляющее большинство объема — это NotAllowedError, и большая его часть — ожидаемое поведение (пользователь закрыл запрос).
  • Как различать NotAllowedError? Используйте время (немедленный отказ против отмены пользователем против таймаута), индикатор QR/гибридного режима (несоответствие доступности), контекст активации пользователем (особенно в iOS/Safari) и тип операции (Conditional UI против модального входа против создания ключа доступа против условного создания). Не относитесь ко всем NotAllowedError как к одному режиму сбоя.
  • Почему тип операции имеет значение? Одно и то же error.name во время входа с помощью Conditional UI — это совершенно другой сигнал, чем при условном создании или ручном создании ключа доступа (пользователь закрыл окно). Запись типа операции вместе с ошибкой — это то, что превращает общее NotAllowedError в категорию, с которой можно работать.
  • Какой минимальный контекст делает ошибки пригодными для отладки? Собирайте error.name, тип операции, время до ошибки с начала операции, тип потока, отображался ли QR/гибридный UI, ОС/браузер/устройство (включая версии), идентификатор корреляции (auth_flow_id) и отказы проверки сервера в виде явных кодов.

Два правила, которые применимы ко всем типам ошибок: никогда не показывайте необработанные ошибки браузера пользователям — всегда предоставляйте четкий резервный путь — и отделяйте локальные попытки от QR/гибридных попыток на разных устройствах, поскольку они терпят неудачу по разным причинам и требуют разных исправлений. В масштабе поддержание классификации ошибок в разных браузерах, версиях ОС и менеджерах учетных данных — это постоянная работа. Рассмотрите возможность использования SDK наблюдаемости с поддерживаемой библиотекой шаблонов, а не создавать ее с нуля.

Corbado

О Corbado

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

Часто задаваемые вопросы#

Как отличить отмену запроса на использование ключа доступа пользователем от отсутствия ключа доступа на устройстве?#

В веб-браузерах оба случая объединяются в NotAllowedError из соображений конфиденциальности, поэтому их нельзя различить напрямую. Используйте время как показатель: ошибка менее 1 секунды обычно означает отказ среды или отсутствие возможности, тогда как 1-15 секунд предполагают, что пользователь увидел и закрыл диалоговое окно. В нативных приложениях iOS и Android установка preferImmediatelyAvailableCredentials перед запросом дает четкий сигнал об отсутствии учетных данных (код 1005 в iOS, GetCredentialRequest в Android) до отображения какого-либо пользовательского интерфейса.

Почему у меня такой высокий уровень ошибок WebAuthn, хотя ключи доступа, кажется, работают для большинства пользователей?#

В оптимизированных масштабных развертываниях ключей доступа более 95% регистрируемых ошибок WebAuthn являются ожидаемыми отменами со стороны пользователя, а не системными сбоями. Отслеживание необработанного количества error.name без отделения закрытия запроса пользователем от подлинных сбоев завышает показатели ошибок и скрывает реальные регрессии внутри объема NotAllowedError. Разделяйте подсчеты по типу операции и рассматривайте сегменты отмены пользователем отдельно от непредвиденных ошибок, таких как SecurityError, ConstraintError и DataError.

Что означает код 1005 ASAuthorizationError в iOS и как его использовать?#

Код 1005 в iOS (NotInteractive) означает, что на устройстве не было доступно ключей доступа, когда preferImmediatelyAvailableCredentials было установлено в ASAuthorizationController, и пользователю не показывался пользовательский интерфейс. Это четкий сигнал «ключ доступа не существует на этом устройстве», который веб-браузеры не могут предоставить из-за ограничений конфиденциальности. Всегда классифицируйте по числовому коду, а не по localizedDescription, поскольку сообщения Apple локализуются на более чем 30 языков и могут меняться в разных версиях ОС.

Как обрабатывать NotAllowedError во время условного создания (conditional create) или автоматически запускаемого добавления ключа доступа?#

Во время условного создания NotAllowedError, AbortError и InvalidStateError являются ожидаемыми результатами и их следует игнорировать, а не выводить как ошибки. NotAllowedError указывает на то, что автозаполнение недоступно или страница потеряла фокус, тогда как InvalidStateError означает, что ключ доступа уже существует у провайдера. Перед попыткой вызова используйте getClientCapabilities() для проверки поддержки conditionalCreate и проверьте состояние видимости документа, чтобы избежать завышения количества ошибок.

Какой контекст следует регистрировать вместе с error.name, чтобы ошибки WebAuthn можно было отлаживать?#

Регистрируйте тип операции (Conditional UI, модальный вход, создание вручную, условное создание или автодобавление), время до ошибки с начала операции, версию ОС, версию браузера, модель оборудования, появлялся ли QR/гибридный интерфейс, и идентификатор корреляции для связи с журналами на стороне сервера. Сбои проверки на сервере, такие как несоответствие challenge, недействительная подпись и не найденные учетные данные, должны регистрироваться как явные структурированные коды, а не смешиваться в одной корзине с именами клиентских DOMException. Эти сигналы вместе позволяют классифицировать подавляющее большинство ошибок в категории, пригодные для действий, без угадывания.

Посмотрите, как Corbado вписывается во внедрение passkeys и текущий стек аутентификации.

Открыть Console

Поделиться статьей


LinkedInTwitterFacebook