このページは自動翻訳されています。英語の原文は こちら.
本番環境におけるWebAuthnエラーは、ブラウザが公開するDOMExceptionの名称(NotAllowedErrorなど)の数が少なく、複数の根本原因を表す可能性があるため、非常にわかりにくいものです。さらに、「エラー」の大部分(最適化された大規模な導入環境では多くの場合95%以上)は、実際には想定内の動作(ユーザーがオペレーティングシステムのパスキープロンプトを中止した)です。
Passkeys Debuggerでパスキーフローを試せます。
重要: プライバシーの理由から、ブラウザはユーザーが意図的にキャンセルしたのか、パスキーが存在しなかったのかを区別しません。ただし、Webとネイティブプラットフォームの両方において、状況と十分なコンテキストがあれば、タイミングなどのシグナルを使用してこれらのケースを区別できる場合があります。
これらの名称の正規の定義を確認したい場合は、まずMDN DOMExceptionを参照してください。これらの例外につながるWebAuthn固有の条件(およびブラウザが強制する必要があるもの)については、W3C Web Authentication仕様を参照してください。
すべてのエラーを「バグ」として扱うと、誤った対応をとることになります。
NotAllowedErrorに隠れた実際の不具合を見逃すこの記事では、以下の疑問に答えます。
NotAllowedErrorをどのようにして対応可能な分類(キャンセル、タイムアウト、可用性など)に明確化するか?NotAllowedErrorは表面的なシグナルであり、根本原因ではありません。コンテキストに応じて、キャンセル、タイムアウト、「ローカルの認証情報がない」、またはユーザーアクティベーションの欠如を意味する可能性があります。NotAllowedErrorでも意味が異なります。AbortErrorは通常、ライフサイクルまたは並行処理の問題(ナビゲーション、再レンダリング、複数の進行中のリクエスト)です。SecurityErrorはほぼ常に設定やコンテキストの問題であり、成熟した本番環境での導入では稀です。error.nameと一緒に操作タイプ、タイミング、プラットフォームのコンテキストをキャプチャしてください。デバッグのブロックを解除するための簡単なマッピングが必要な場合は、まずこの表から始めてください。これは、チームがダッシュボードやサポートチケットで実際に目にする情報に偏っています。
error.name | 本番環境で通常意味するもの | 確認事項 | 最初のアクション(UX + エンジニアリング) |
|---|---|---|---|
NotAllowedError | ユーザーがシートを閉じた、タイムアウトした、または可用性の不一致が1つの分類にまとめられたもの。本番環境で最も多いエラー分類です。 | エラーまでの時間、QR/ハイブリッドUIが表示されたかどうか、セレモニーが実際のユーザーアクションから開始されたかどうか | 想定内として扱う:UIを復元し、フォールバックを表示する |
AbortError | アプリ(またはブラウザ)がセレモニーを中止した | セレモニー中のナビゲーション/再レンダリング、同時並行のWebAuthn呼び出し、AbortController.abort() | 進行中のリクエストを1つに制限する、ルート変更を防ぐ、中止を通常の制御フローとして処理する |
SecurityError | コンテキスト/ポリシーが許可されていない | オリジンとRP ID戦略、iframe/埋め込み、HTTPS、機能ポリシー | RP ID/オリジンの設定を修正する、埋め込みポリシーを検証する、セキュアコンテキストを確保する |
InvalidStateError | 状態の不一致(多くの場合、重複した登録) | 登録とログイン、excludeCredentials、Authenticator上の既存の認証情報 | 「すでに登録済み」として扱う、UXパスを調整する、オプション生成を修正する |
ConstraintError | 要件を満たせない | authenticatorAttachment、userVerification、常駐キーの要件 | 制約を緩和するか、代替パス/フォールバックを提供する。例:Androidで画面ロックが設定されていない |
DataError | 入力が不正/矛盾している | base64urlエンコーディング、ID/チャレンジ/ユーザーハンドルの形式 | エンコーディング/シリアライズを修正する、オプション生成で検証を追加する |
NotSupportedError | プラットフォーム/ブラウザが要求された機能をサポートしていない | OS/ブラウザのバージョン、機能検出の前提 | すぐにフォールバックする、セグメントを記録する、サポートされていない環境ではパスキーのCTAを表示しない |
UnknownError | プラットフォーム/Authenticatorが一般的な方法で失敗した | OSアップデート後の急増、デバイスビルド、Credential Managerプロバイダーの問題 | 再試行しやすいUXにする、ビルド番号をキャプチャする、セグメントの急増を調査する |
見落としがちなこととして、同じerror.nameでも操作タイプによって意味が全く異なる場合があります。以下のセクションを読む際は、操作のコンテキストに留意してください。実際には、パスキーの作成(登録)エラーはログインエラーを大きく上回るのが通常です。上の表は両方に適用されますが、ボリュームの大部分は作成時に発生します。
次に、チームが最も頻繁に目にし、最も誤解しやすいNotAllowedErrorについて深く掘り下げます。
NotAllowedErrorは「パスキーが失敗した」ように見えることが多いですが、通常はプラットフォームが「ユーザーがOSのUIを完了しなかった」と伝えているものです。重要なのは、それを対応可能な分類に分けることです。
ブラウザのコンソールに表示される内容:
| ソース | エラーメッセージ |
|---|---|
| Chrome, Edge | NotAllowedError: The operation either timed out or was not allowed. See: https://www.w3.org/TR/webauthn-2/#sctn-privacy-considerations-client. |
| Safari, WebKit | NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission. |
| Safari, WebKit | NotAllowedError: This request has been cancelled by the user. |
| Chrome, Edge | NotAllowedError: The operation is not allowed at this time because the page does not have focus. |
| Safari, WebKit | NotAllowedError: The document is not focused. |
| Firefox | NotAllowedError: Operation failed. |
これらはすべてerror.name === "NotAllowedError"として表面化します。error.messageはブラウザエンジンや根本原因によって異なりますが、結果は同じで、セレモニーが完了しなかったということです。
これはログインとパスキーの作成の両方に適用されます。ログイン中(条件付きUI、allowListの有無にかかわらないモーダル)のNotAllowedErrorは、通常、ユーザーがセレモニーを完了しなかったことを意味します。パスキーの作成中にも、異なる理由で同じエラーが表面化します。ユーザーが作成ダイアログを閉じた(条件付き作成が機能しなかった)、または自動トリガーによる追加中にページがフォーカスを失った場合などです。操作タイプによってエラーの意味と対処法が変わります。
タイミングは過小評価されがちなシグナルです。 クリックから1秒未満のエラーは、通常、即時の拒否(環境が実行できない、ドキュメントにフォーカスがない、機能がない)です。数秒後のエラーはユーザーのキャンセル(ダイアログを見て進めないことを決定した)です。30秒以上経過した後のエラーはタイムアウトです。ネイティブプラットフォームではタイミングが特に重要で、Authenticatorのラウンドトリップ、生体認証プロンプト、Credential Managerのハンドオフにはそれぞれ特徴的な所要時間があり、「機能しなかった」のか「ユーザーが離れた」のかを区別するのに役立ちます。それでも、パスキーが存在したかどうかを簡単に区別することはできません。
完璧なシグナルは必要ありません。すべてのNotAllowedErrorを同じように扱わないようにするための十分なコンテキストが必要です。iOS/Safariについては、独自の制約(以前のバージョンでのユーザーアクティベーション要件)があるため以下で特に注意を向けますが、生のエラーボリュームで見ると、WindowsとChromiumブラウザは他のどのプラットフォームよりも多くのNotAllowedErrorを生成することがよくあります。これらのシグナルを活用することで、多くの場合80%の対応が可能になります。
| シグナル | 可能性の高い意味 | 次のアクション |
|---|---|---|
| 即時の失敗(1秒未満) | 環境の拒否:機能がない、ドキュメントにフォーカスがない、条件付き作成サーフェスが利用できない | 機能検出を確認する、ドキュメントにフォーカスがあるか確認する、このプラットフォームで操作がサポートされているか検証する |
| 早いキャンセル(1〜3秒) | 予期せぬプロンプト / コンテキストがない | プロンプトのタイミングを変更する、キャンセル後にクールダウンを追加する |
| ユーザーの長さのキャンセル(3〜15秒) | ユーザーがダイアログを見て進めないことを選んだ | 想定内のUX:UIを復元し、フォールバックを表示する |
| タイムアウト(30秒以上) | ユーザーのアクションなしにセレモニーがタイムアウトした | 「完了しなかった」として分類する、プロンプトが気づかれていたかどうか検討する |
| 失敗の前にQR/ハイブリッドUIが表示される | このデバイスで利用可能なローカルの認証情報がない。注:QRコードの決定が行われる前に確実に検出するには、現在のデバイスで使用可能な認証情報が存在するかどうかを把握するパスキーインテリジェンスレイヤーが必要です。 | パスキーの提案を制限する、「スマートフォンを使用する」を明示する、予期せぬQRを減らす |
| iOS/Safariに集中しており、クリック/タップなしでトリガーされる | ユーザーアクティベーションの欠如 | 実際のユーザーのジェスチャーからセレモニーを開始する |
| 条件付き作成または自動トリガーによる追加中 | 自動入力が利用できない、認証情報がすでに存在する、またはページがフォーカスを失った。条件付き作成エラーは、機能がリリースされると突然大量に発生する可能性があり、一晩で最大のエラーソースの1つになります。 | 条件付き作成を確認する、ドキュメントの表示状態を確認する、呼び出しを試行する前にgetClientCapabilities()を使用してconditionalCreateのサポートを検証する |
これもNotAllowedErrorをユーザーに表示すべきではない理由の1つです。これはユーザーが対応できるメッセージではありません。
コンテキストの分類は、成功率が最も大きく分かれる部分でもあります。Corbadoのパスキーベンチマーク2026年 パスキー認証成功率分析によると、大規模なB2C展開において、未知のデバイスでの識別子ファーストフローの完了率が55〜95%であるのに対し、既知のデバイスの再訪問では95〜99%となっています。iOS Webの識別子ファーストは完了率が85〜95%(CDA 0〜5%)、Android Webは70〜85%(CDA 5〜10%)、macOS Webは70〜85%(CDA 10〜15%)に着地しますが、Windows Webの識別子ファースト完了率は45〜60%で、CDAの割合はWindows 11で55〜65%、Windows 10で40〜55%です。既知のデバイスと未知のデバイスのコンテキストを分けずにNotAllowedErrorのボリュームを読み取ると、根本的に異なる2つの成功の状況を混同することになります。
本番環境で重要なニュアンスが1つあります。一部のユーザーエージェントはタイムアウトをTimeoutErrorとして表示する場合がありますが、多くのチームはダッシュボードでタイムアウトがNotAllowedErrorに統合されているのを目にします。いずれにせよ、タイムアウトは「セレモニーが完了しなかった」として扱い、タイミングとコンテキストを使用して分類してください。
OSのシートが閉じられたりタイムアウトしたりした場合、UIは即座に回復し、適切に反応する必要があります。実用的なルールのセットは以下の通りです。
基本を超えた対応:
「キャンセル」が本当に多い場合、次のステップは、プロンプトのタイミング、予期せぬQR、可用性の低さなど、その背後にある根本原因を修正することです。
指標をすばやく改善できる変更から始めます。
NotAllowedErrorの分類が膨れ上がらないようにします。最も基本的な制限としてisUVPAA()から始め、次にgetClientCapabilities()を使用してより詳細なチェック(条件付き作成、条件付き取得、ハイブリッドトランスポート、プラットフォームAuthenticator)を行います。検出APIはOSのアップデートによって壊れる可能性があることに注意してください。iOS 26.2では、パスキーが正常に機能するにもかかわらず、すべてのWKWebViewベースのブラウザでisUVPAA()がfalseを返すというWebKitのバグが含まれており、iOSユーザーの10〜25%でNotAllowedErrorが急増しました。エラー名は常に変化しています。より詳細なWebAuthnエラーを追加する(たとえば、「利用可能な認証情報がない」ことと「ユーザーがキャンセルした」ことを分けるなど)継続的な提案があります。2026年2月現在、これはどのブラウザにも実装されていないため、コンテキストとタイミングに基づいて独自の理由の分類を構築する価値は依然としてあります。この作業を追跡したい場合は、WebAuthnのIssue #2062と、"New Error Codes" explainerを参照してください。
残りのエラー名は頻度が低いですが、出現した際に理解しておく価値があります。
AbortErrorはNotAllowedErrorに比べて量は少ないですが、出現した場合の診断価値は高いです。これは通常、アプリがリクエストを無効にした(ナビゲーションが発生した、状態が変わった、または2番目のリクエストが開始された)ためにセレモニーが終了しなかったことを意味します。
ブラウザのコンソールに表示される内容:
| ソース | エラーメッセージ |
|---|---|
| Chrome, Edge | AbortError: The operation was aborted. |
| Chrome, Edge | AbortError: Aborted by AbortSignal. |
| Firefox | AbortError: signal is aborted without reason |
| Firefox | AbortError: Operation timed out. |
| Safari, WebKit | AbortError: The user aborted a request. |
| Chrome | AbortError: CredentialContainer request is not allowed. |
本番環境での一般的な原因には以下が含まれます。
AbortController.abort()の呼び出しこれを修正するには、セレモニーを「クリティカルセクション」にすることに焦点を当てます。
埋め込みサーフェスやマルチドメインアプリでAbortErrorが集中しているのを見つけた場合、次に確認すべき分類はSecurityErrorです。
SecurityErrorは、ブラウザが「このコンテキストでは要求された操作が許可されていません」と伝えているものです。実際には、ユーザーの行動ではなく設定に問題があることがほとんどです。成熟した本番環境での導入では、これらの問題は通常統合テスト中に捕捉されるため、SecurityErrorはまれです。本番環境で発生した場合、通常は適切なWebAuthn構成なしに新しいドメイン、埋め込みコンテキスト、またはデプロイメントターゲットが追加されたことを意味します。
一般的な原因には以下が含まれます。
.well-known/webauthn または .well-known/assetlinks.jsonの設定ミス、欠落、または一時的な利用不可。ブラウザがこれらのファイルをフェッチする重要な時間枠でのネットワーク問題は、失敗の原因となります。よくある盲点:ホームページがメンテナンスでダウンしている場合、well-knownファイルもオフラインになり、それらに依存するすべてのRelying Partyでパスキーのセレモニーが中断されます。ブラウザのコンソールに表示される内容:
| ソース | エラーメッセージ |
|---|---|
| Chrome, Edge | SecurityError: 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証明書エラーが最も一般的な残存エラーです。
最も速いデバッグループは以下の通りです。
publickey-credentials-create / publickey-credentials-get):MDN Permissions-PolicySecurityErrorが処理された後、次に真剣に扱うべき分類は、多くの場合実装のバグを示すエラー群であるInvalidStateError、ConstraintError、およびDataErrorです。

Passkeysチートシート. パスキープログラム向けの実践ガイド、展開パターン、KPI。
これらのエラーは、成熟したパスキーの実装ではまれなはずです。これらが表示された場合、通常はセグメントのオプション生成が間違っているか、フローが間違った状態にあることを示しています。
ブラウザのコンソールに表示される内容:
| ソース | エラーメッセージ |
|---|---|
| Safari, WebKit | InvalidStateError: The user attempted to register an authenticator that contains one of the credentials already registered with the relying party. |
| Chrome, Edge | InvalidStateError: At least one credential matches an entry of the excludeCredentials list in the platform attached authenticator. |
| Chrome, Edge | InvalidStateError: A request is already pending. |
| Firefox | InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable |
典型的な意味:
実用的な処理:
excludeCredentialsにユーザーのすべての既存の認証情報IDがリストされていることを確認します。InvalidStateErrorは想定内であり、無視すべきです。これは、プロバイダーにパスキーがすでに存在することを意味します。条件付き作成中のNotAllowedErrorおよびAbortErrorにも同じことが当てはまります(Chromeでの条件付き作成を参照)。典型的な意味:Authenticatorが要求された制約を満たすことができません。
一般的なトリガー:
authenticatorAttachmentまたは常駐キーの前提userVerificationが利用できないセグメントでのハードな要件修正:制約を緩和する(許容される場合)か、代替パスを提供します。画面ロックがない場合、何も言わずに失敗するのではなく、この状態を検出してユーザーをガイドすることを検討してください(Android)。
典型的な意味:入力が不正であるか、矛盾しています。
一般的なトリガー:
修正:WebAuthnオプションを生成する境界で入力を検証し、正規化します。実際には、成熟した本番システムではDataErrorは実質的に存在しません。オプション生成がテストされていれば、ダッシュボードでこれを見ることはありません。
これらのエラーがコントロール下にある場合、次の疑問はカバレッジです。環境が期待通りの方法でWebAuthnを実行できないためにユーザーが失敗しているのでしょうか?
NotSupportedErrorはカバレッジのシグナルであり、信頼性のシグナルではありません。通常、セグメントが要求されたことを実行できない(OS/ブラウザが古すぎる、機能が欠けている、機能が有効になっていない)ことを意味します。
ブラウザのコンソールに表示される内容:
| ソース | エラーメッセージ |
|---|---|
| Chrome, Edge | NotSupportedError: The user agent does not support public key credentials. |
| Firefox | NotSupportedError: Resident credentials or empty 'allowCredentials' lists are not supported. |
| Chrome, Edge, Firefox | TypeError: PublicKeyCredential.parseCreationOptionsFromJSON is not a function |
| Chrome, Edge, Firefox | TypeError: PublicKeyCredential.parseRequestOptionsFromJSON is not a function |
| Chrome, Edge, Firefox | TypeError: credential.toJSON is not a function |
| Safari | TypeError: Can only call PublicKeyCredential.toJSON on instances of PublicKeyCredential |
最初の2つは本物のNotSupportedErrorのDOMExceptionsです。TypeErrorのエントリは技術的には異なる例外タイプですが、同じクラスの問題、つまりブラウザや環境が要求されたものをサポートしていないことを表しています。JSONシリアライゼーションのTypeErrorファミリーは、実際にはNotSupportedError DOMException自体よりもはるかに一般的です(下記参照)。
一般的な原因には以下が含まれます。
JSONシリアライゼーションファミリーは、本番環境におけるNotSupportedErrorクラスの障害の最大の原因です。 技術的にはこれらはDOMExceptionではなくTypeError(メソッドの欠落)として表面化しますが、ここで遭遇することになります。2つの明確な根本原因があります。
navigator.credentialsはありますが、PublicKeyCredential.parseCreationOptionsFromJSON / parseRequestOptionsFromJSONはありません。これは、このエラーファミリーの約90%を占め、古いバージョンのSafariとChromeに集中しています。クライアントライブラリがフォールバックなしにこれらのメソッドに依存している場合、これにより大量のエラーが発生します。.toJSON()を壊す。 Bitwarden、LastPass、または1Passwordなどの拡張機能は、セレモニーを傍受し、認証情報のように見えるが実際のPublicKeyCredentialインスタンスではないオブジェクトを返す可能性があります。これに対して.toJSON()を呼び出すと、エラーがスローされるか、undefinedが返されるか、オブジェクトが完全にnullになります。これはこのファミリーの約10%を占めますが、エラーメッセージがブラウザによって異なる(Safari:「Can only call on instances of PublicKeyCredential」、Firefox:「does not implement interface PublicKeyCredential」)ため、デバッグが特に困難です。対処は直接的かつ迅速に行う必要があります。
カバレッジが良好に見えても、特定のセグメントで障害が発生する場合は、UnknownErrorとして表面化したプラットフォームレイヤーの問題に対処している可能性があります。
UnknownErrorは、他のカテゴリにきれいにマッピングされないAuthenticator/OSの障害のキャッチオールです。一時的なものであることが多いですが、OSのアップデート後に急増することもあります。
ブラウザのコンソールに表示される内容:
| ソース | エラーメッセージ |
|---|---|
| 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 |
実用的な処理:
どのDOMExceptionカテゴリにもきれいに当てはまらないニッチなエラーソースの1つに、パスワードマネージャーのブラウザ拡張機能(Bitwarden、LastPass、1Passwordなど)があります。これらはWebAuthn API呼び出しを傍受し、非標準のレスポンスを返す可能性があります。ユーザーのキャンセルと比較すると量は少ないですが、特定のユーザーセグメントに一貫して影響を与え、症状(返された認証情報オブジェクトのメソッドの欠落、予期しないエラータイプ、または文書化されたWebAuthnエラーと一致しない不正なレスポンス)がわかりにくいため、追跡する価値があります。これらは多くの場合、UnknownErrorとして、または分類されない例外として表面化します。OSレベルでの説明がつかない特定のブラウザに集中したエラーの急増が見られる場合は、Credential Manager拡張機能が関与していないか確認してください。
これまではWebブラウザのエラー名を取り上げてきました。しかし、ネイティブアプリも提供している場合、エラーの状況は異なり、ある意味で大幅に改善されています。
上記のすべてはWebブラウザに関するものです。ネイティブアプリ(ASAuthorizationフレームワークを使用するiOS、Credential Managerを使用するAndroid)は、同じ基本的なエラーカテゴリを共有していますが、重要な点で異なります。
「認証情報がない」は明確なシグナルです。 Webでは、プライバシー保護のためにブラウザが「利用可能な認証情報がない」ことと「ユーザーがキャンセルした」ことを同じNotAllowedErrorに統合します。ネイティブでは、iOS(ASAuthorizationController)でpreferImmediatelyAvailableCredentialsを使用するか、Android(GetCredentialRequest)でsetPreferImmediatelyAvailableCredentials(true)を使用すると、デバイスにすでに存在する認証情報のみを提示し、存在しない場合はすぐに失敗するようにOSに指示します。これにより、Webでは提供できないクリーンな「認証情報がない」という結果が得られます。
Credential Providerのステータスが可視化されています。 ネイティブプラットフォームでは、特定の状況下で、Credential Provider(Google Password Manager、iCloudキーチェーン、1Passwordなど)がインストール、設定、またはデフォルトとして設定されていないことを把握し、それに対応することができます。Web上では、この情報は不透明なNotAllowedErrorメッセージの後ろに隠されています。
エラーメッセージがより具体的です。 ユーザーがアプリをインストールしており、それによってRelying Partyとの信頼関係が確立されているため、OSはより詳細な診断情報を表示します。アプリがすでにデバイス上にある場合、Webブラウザを曖昧にするプライバシーの考慮事項は同じようには適用されません。iOSはユーザーのデバイス言語にローカライズされたメッセージを返します。Androidは原因チェーンを含む構造化されたエラータイプを返します。これによりデバッグが容易になりますが、エラー処理ではローカリゼーションとプラットフォーム固有のエラーフォーマットを考慮する必要があります。
iOSは、ASAuthorizationフレームワークを通じてパスキーエラーを表示します。すべてのエラーは、authorizationController(controller:didCompleteWithError:) デリゲートコールバックにNSErrorオブジェクトとして到達します。
メッセージ文字列ではなく、ドメイン + コードで分類します。 主なエラードメインはcom.apple.AuthenticationServices.AuthorizationError(ASAuthorizationError.errorDomain)です。let nsError = error as NSErrorでエラーをキャストし、.domainと.codeで一致させます。本番環境で.localizedDescriptionと照合しないでください。Appleのメッセージは30以上の言語にローカライズされており、OSバージョン間で変更される可能性があります。以下にリストされているメッセージ文字列は、ログ内のエラーを認識するのに役立ちますが、分類の基準ではありません。
公開されているASAuthorizationErrorコード:
| コード | 名前 | 導入 | 意味 |
|---|---|---|---|
| 1000 | Unknown | iOS 13 | 本番環境には表示されないはずです。一般的なキャッチオール。 |
| 1001 | Canceled | iOS 13 | ユーザーがパスキーのシートを閉じました。全体で最も多いエラーであり、NotAllowedErrorに相当します。空のuserInfoと根本的なエラーのないクリーンなシグナル。 |
| 1002 | InvalidResponse | iOS 13 | フレームワークレベルの破損。実際にはまれです。 |
| 1003 | NotHandled | iOS 13 | リクエストを処理したプロバイダーはありません。エンタイトルメントとCredential Providerの設定を確認してください。 |
| 1004 | Failed | iOS 13 | 一般的な失敗。localizedDescriptionに実際の理由(例:「識別子Xを持つアプリケーションはドメインYに関連付けられていません」)が含まれています。userInfoにはFailureReason文字列が含まれる場合がありますが、NSUnderlyingErrorKeyは常に存在するとは限りません。ドメインの関連付けの失敗ではnilが返されます。 |
| 1005 | NotInteractive | iOS 15 | preferImmediatelyAvailableCredentialsを使用した場合に利用可能な認証情報がありません。これはクリーンな「見つからない」シグナルであり、「このデバイスにパスキーは存在しない」というiOS版です。UIは表示されませんでした。 |
| 1006 | MatchedExcludedCredential | iOS 18 | このデバイスのこのRPにはパスキーがすでに存在します。重複検出のためのクリーンなシグナルです。空のuserInfoでNSUnderlyingErrorKeyはありません。文字列のマッチングなしで分類が機能します。 |
| 1007 | CredentialImport | iOS 18.2 | 認証情報のインポートに失敗しました。 |
| 1008 | CredentialExport | iOS 18.2 | 認証情報のエクスポートに失敗しました。 |
| 1009 | PreferSignInWithApple | iOS 26 | ユーザーがパスキーよりも「Appleでサインイン」を優先しています。iOS 26の新機能。 |
| 1010 | DeviceNotConfiguredForPasskeyCreation | iOS 26 | デバイスにパスコードまたはiCloudキーチェーンの設定がありません。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 X | 1004 (Failed) | アプリのAssociated DomainsエンタイトルメントがRelying Partyと一致していません。サーバー上のapple-app-site-associationファイルを修正してください。 |
Couldn't communicate with a helper application. | 1004 (Failed) | Credential Provider拡張機能が応答しませんでした。一時的なものなので、再試行が適切です。 |
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.) | 別ドメイン | クロスデバイス認証(ハイブリッド/CABLE)のBluetoothハンドシェイクが失敗しました。 |
(AuthenticationServicesCore.ASCABLEClient.ClientError error 3.) | 別ドメイン | クロスデバイス認証のBluetooth接続が失敗しました。 |
ローカライズされた「認証情報がありません」というメッセージ(コード1005):
preferImmediatelyAvailableCredentialsが設定されており、パスキーが存在しない場合、iOSはユーザーのデバイス言語にローカライズされたメッセージとともにコード1005(NotInteractive)を返します。これはネイティブアプリに固有のものであり、Webブラウザがこのシグナルを公開することはありません。メッセージは常に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. |
英語ロケールのデバイスは、通常、ASAuthorizationフレームワークがローカライズされたエラーを返す前に、APIレベルで「認証情報がない」状態を解決するため、上記に英語のバリエーションは表示されていません。プログラム上は、これらの文字列を解析するのではなく、常にコード1005で照合してください。
Androidは、Credential Manager API(androidx.credentials)を通じてパスキーエラーを表示します。エラーメッセージにはプライマリメッセージが含まれ、多くの場合、追加の詳細を示すcauseが含まれます。iOSと比較して、Androidはより構造化されたエラータイプと、設定の問題に対するより明確な原因を提供します。
ユーザーのキャンセルと認証情報の検出:
| エラー | メモ |
|---|---|
User cancelled the operation | ユーザーがパスキーのプロンプトを閉じました。NotAllowedErrorに相当します。注:Credential Managerは別のコードパスからもUser canceled the request(USスペル)を返しますが、両者は同じです。 |
Excluded credential matches existing credential | この認証情報IDにはパスキーがすでに存在します。InvalidStateErrorに相当します。iOSとは異なり、メッセージはユーザーのキャンセルとは区別されます。 |
No create options available. | 作成リクエストを処理できる適格なCredential Providerがありません。通常、Google Play開発者サービスが古すぎるか、パスキーの作成をサポートしているCredential Providerがないことを意味します。 |
構成およびセキュリティエラー:
| エラー | メモ |
|---|---|
Passkeys not supported for this app | Digital 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 validated | Credential ManagerはDigital Asset Linksに対するリクエストを検証できません。 |
RP ID cannot be validated. | WebAuthnオプションのRelying Party IDがassetlinks.jsonと一致していません。 |
Screen lock is missing. | デバイスにPIN、パターン、または生体認証が設定されていません。パスキーにはユーザー検証が必要です。ConstraintErrorに相当します。 |
Cannot find an eligible account. | デバイス上のGoogleアカウントで、パスキーの作成に適格なものがありません(まれであり、通常はカスタムのエンタープライズセットアップです)。 |
プラットフォームおよびAuthenticatorエラー:
| エラー | メモ |
|---|---|
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のUIが別のアクティビティ(着信、画面の回転、アプリのバックグラウンド化)によって中断されました。AbortErrorに相当します。 |
Unknown credential error | 特定のエラータイプが当てはまらない場合の一般的なキャッチオール。通常は一時的なものです。 |
timeout (cause: Canceled) | ユーザーが生体認証を完了する前に、Credential Managerの操作がタイムアウトしました。 |
以下の図は、上記で説明したすべてのレイヤー(インフラストラクチャ、環境、操作タイプ、分類、および検出)がエンドツーエンドでどのようにつながっているかを示しています。これは、エラー追跡を設計する際に念頭に置くべきメンタルモデルです。
重要な洞察:生のエラー名(error.name)は、環境のどのレイヤーがそれを生成したか、どの操作が実行されていたか、そしてそのエラーが想定内か予期しないものかを知って初めて意味を持ちます。以下のセクションでは、何を記録し、どのように対処するかについて説明します。
この記事でのエラー分類のほとんどは、クライアント側のシグナルだけで実行できます。フロントエンドのみのオブザーバビリティSDKは、WebAuthnエラーの大部分を分類するのに十分なコンテキストをキャプチャします。これは、CorbadoのオブザーバビリティSDKの設計でもあります。クライアント側のレイヤーが、エラーの原因特定、タイミング、操作コンテキスト、およびプラットフォーム検出を処理します。サーバー側のログは、バックエンドだけが見ることができる失敗に対して第2のレイヤーを追加します。
主な要件:すべての試行はエンドツーエンドで結合可能でなければなりません。共有された相関ID(例:auth_flow_id)により、クライアント側のコンテキストとサーバーの検証結果が結び付けられます。
| シグナル | 重要である理由 |
|---|---|
error.name + 正規化された理由の分類 | 生のブラウザエラー + あなたの分類 |
| 操作タイプ | 条件付きUI、モーダルログイン、手動での作成、条件付き作成、自動追加。**CDA(クロスデバイス認証)**はそれ自体が複雑なものです。 |
| 完全な環境のコンテキスト | OS + バージョン、ブラウザ + バージョン、ハードウェアのブランド/モデル、Authenticatorの設定(例:GPMは有効か?) |
| Authenticator / Credential Managerのコンテキスト | 拡張機能およびプロバイダーの破損 |
| 操作開始からのエラー発生までの時間 | 即時の拒否(1秒未満)対ユーザーのキャンセル(1〜15秒)対タイムアウト(30秒以上) |
| ネットワーク / 接続状態 | ネットワークエラーはクライアントエラーとして現れることがよくあります。ユーザーがオフラインであったかどうかを追跡し、接続が復元したときに送信するようにログをキューに格納します。 |
| QR/ハイブリッドUIが表示されたかどうか | ローカルの失敗とクロスデバイスの失敗 |
相関ID(auth_flow_id) | サーバーのログと結合する |
サーバーの検証の失敗は、ブラウザが認証情報と署名付きのチャレンジを返した後に発生します。これらは、クライアント側のDOMException名と同じ分類に含めるのではなく、明示的なコードを使用した構造化されたエラーにする必要があります。WebAuthnのサーバーの実装を参照してください。
| シグナル | 重要である理由 |
|---|---|
| チャレンジの不一致 / 期限切れのチャレンジ | セッションのタイミングまたはリプレイの問題 |
| オリジン / RP IDの不一致 | マルチドメインの設定バグ |
| 無効な署名 / 認証情報が見つからない | 削除または破損した認証情報。よくあるケース:ユーザーがサーバー側ですでに削除したパスキーを使用した条件付きUIログイン。Signal APIを使用して、クライアントとサーバーの認証情報リストを同期させます。 |
| ユーザーハンドルの不一致 | アカウントのマッピングの問題 |
相関ID(auth_flow_id) | クライアント側のコンテキストと結合する |
(ステップごとの離脱やステップ間のコンバージョンなど)完全なファネルモデルが必要な場合は、離脱を理解するためのパスキーテレメトリを参照してください。
最新ニュースを受け取るためにPasskeys Substackを購読しましょう。
このデータが整備されると、結論はシンプルになります。ほとんどの「エラー」は、UXの修正、カバレッジの修正、または設定の修正のいずれかになります。しかし、この分類を自分で構築して維持することは、継続的で多大な作業となります。
上記のログチェックリストは生のシグナルをキャプチャします。大規模な本番環境では、error.nameだけでは十分ではありません。この分類を自分で構築することは、継続的で多大な作業となります。エラーメッセージはブラウザやOSのリリースごとに変更され、パスワードマネージャーのプロバイダーはセレモニーの動作を変更するアップデートを提供し、機能がリリースされるたびに新しいエラーのシグネチャが現れます。
error.nameだけでは不十分な理由#ブラウザが分離してくれない3つの側面に応じて、同じNotAllowedErrorでも6つの異なる意味を持つ可能性があります。
| 次元 | ブラウザが提供するもの | 実際に必要なもの | 例 |
|---|---|---|---|
| 操作のコンテキスト | NotAllowedError | 条件付きUI、モーダルログイン、手動作成、条件付き作成、または自動追加のどれだったか? | Androidは、ログインの却下(想定内)と作成の失敗(予期しない)で同じ「不明なエラー」を返します |
| タイミング | 所要時間のデータなし | 即時(1秒未満)対ユーザーのキャンセル(1〜15秒)対タイムアウト(30秒以上) | 200ms = 環境の拒否、5s = ユーザーがダイアログを見てキャンセル、35s = タイムアウト |
| プラットフォーム + Authenticator | 一般的なerror.name | すべてのエラーについてのOS、ブラウザ、バージョン、Credential Manager | Chromeの「ユーザーがダイアログを閉じた」とSafariの「自動入力が利用できない」はどちらもNotAllowedErrorとして表面化します |
これは、CorbadoのオブザーバビリティSDKが解決するために構築された問題です。これは既存のパスキー実装の上に配置される軽量なフロントエンド統合であり、任意のWebAuthnサーバーと任意のIDPで動作し、すべてのWebAuthnエラーを3つの次元すべてにわたって自動的に分類します。
| 機能 | 実行内容 |
|---|---|
| エラーの原因特定 | セレモニーの試行ごとに、OS、OSのバージョン、ブラウザ、ブラウザのバージョン、およびAuthenticatorをキャプチャします。 |
| 操作モード | 各エラーを特定の操作(条件付きUI、モーダルログイン、手動での作成、条件付き作成、自動追加)に結び付け、同じNotAllowedErrorを異なる根本原因へと解決します。 |
| アクション開始からのタイミング | セレモニーの開始から所要時間を記録し、推測することなく、即時の拒否、ユーザーのキャンセル、タイムアウトを区別します。 |
| インテリジェントなエラー分類 | (名前だけでなく)完全なエラーコンテキストで一致させ、多様な環境(OS、ハードウェア、設定)にわたって正規化します。CDAとローカルなどの個別のエラーグループを優先し、**想定内(ユーザーによる中止)と予期しない(システム障害)**エラーを区別します。 |
| パスワードマネージャーの断片化 | Credential Manager拡張機能(Bitwarden、1Password、LastPass)がセレモニーを傍受し、非標準のレスポンスを返したことを検出し、拡張機能による障害をプラットフォームの障害から分離します。 |
これはObserve(監視)レイヤーであり、実装を変更することなく何が起こっているかを可視化します。
Corbadoの管理コンソールは、2つの調査パスをサポートしています。
トップダウン(ダッシュボードから根本原因へ):
ボトムアップ(エラーパターンから影響度へ):
両方のパスは集束します。トップダウンは「何かが間違っていること」を示し、ボトムアップは「その理由」を示します。AIアナリティクスアシスタントは、エラーデータと導入指標の両方について自然言語で質問できるようにすることで、この2つを結び付けます。
これらのシグナルに基づいて行動したいチームはAdoptに移行し、パスキーインテリジェンスを追加して、自動的にセレモニーを制限し、登録プロンプトを最適化し、壊れたパスキーの状態を修復することができます。規制環境やハイパースケールの導入では、Enterpriseによりシングルテナントのホスティング、SIEMの統合、PSD2準拠の設定が追加されます。
企業向けの無料パスキーホワイトペーパーを入手できます。
WebAuthnのエラー名は結果ではありません。これらはヒントであり、操作タイプ、タイミング、プラットフォームのコンテキストと結び付けて初めて実行可能なものになります。
NotAllowedError)、アプリのライフサイクル/並行処理(AbortError)、セキュリティコンテキスト/設定(SecurityError)、またはオプション/状態のバグ(InvalidStateError、ConstraintError、DataError)という少数のレイヤーにマッピングされます。ボリュームの大部分はNotAllowedErrorであり、そのほとんどは想定内の動作(ユーザーがプロンプトを閉じた)です。NotAllowedErrorをどのように明確化するか? タイミング(即時の拒否、ユーザーのキャンセル、タイムアウト)、QR/ハイブリッドインジケーター(可用性の不一致)、ユーザーアクティベーションのコンテキスト(特にiOS/Safari)、および操作タイプ(条件付きUI、モーダルログイン、パスキー作成、条件付き作成)を使用します。すべてのNotAllowedErrorを同じ失敗モードとして扱わないでください。error.nameは、条件付き作成や手動でのパスキー作成(ユーザーがダイアログを閉じた)とは完全に異なるシグナルです。エラーとともに操作タイプを記録することで、一般的なNotAllowedErrorがアクション可能な分類に変わります。error.name、操作タイプ、操作開始からの時間、フロータイプ、QR/ハイブリッドUIが表示されたかどうか、OS/ブラウザ/デバイス(バージョンを含む)、相関ID(auth_flow_id)、および明示的なコードとしてのサーバーの検証拒否をキャプチャします。すべてのエラータイプに共通する2つの経験則は、「生のブラウザエラーをユーザーに表示しないこと(常に明確なフォールバックパスを提供すること)」、そして「失敗の理由が異なり、異なる修正が必要となるため、ローカルでの試行とQR/ハイブリッドでのクロスデバイスの試行を分けること」です。大規模な環境では、ブラウザ、OSバージョン、Credential Managerにまたがるエラー分類の維持は継続的な作業となります。ゼロから構築するのではなく、維持されたパターンライブラリを備えたオブザーバビリティSDKの使用を検討してください。
Corbadoは、大規模なconsumer認証を運用するCIAMチームのためのAuthentication Intelligence Platformです。IDPのログや一般的なanalyticsツールでは見えないものを可視化します。どのデバイス、OSバージョン、ブラウザ、credential managerがpasskeyに対応しているか、なぜ登録がログインにつながらないのか、WebAuthnフローのどこで失敗するか、OSやブラウザのアップデートがいつ静かにログインを壊すか — Okta、Auth0、Ping、Cognito、あるいは自社IDPを置き換えることなく、すべてを把握できます。2つのプロダクト:Corbado Observeは passkeyとその他あらゆるログイン方式のobservabilityを提供します。Corbado Connectは analytics内蔵のmanaged passkeyを追加します(既存のIDPと併用)。VicRoadsはCorbadoで500万人超のユーザーにpasskeyを提供しています(passkey有効化率+80%)。 Passkeyエキスパートに相談する →
Webでは、プライバシー上の理由からブラウザが両方のケースをNotAllowedErrorに統合するため、直接区別することはできません。タイミングを代用として使用してください。1秒未満のエラーは通常、環境による拒否または機能がないことを意味し、1〜15秒はユーザーがダイアログを見て閉じたことを示唆します。ネイティブのiOSおよびAndroidアプリでは、リクエストの前にpreferImmediatelyAvailableCredentialsを設定することで、UIが表示される前にクリーンな「認証情報がない」シグナル(iOSのコード1005、AndroidのGetCredentialRequest)を得ることができます。
最適化された大規模なパスキーの導入環境では、記録されるWebAuthnエラーの95%以上はシステム障害ではなく、想定内のユーザーによる中止です。「ユーザーがプロンプトを閉じた」ことを真の失敗から分離せずに、生のerror.nameのカウントを追跡すると、エラーの指標が膨れ上がり、NotAllowedErrorの量の中に隠された実際の後退を覆い隠してしまいます。カウントを操作タイプごとに分け、ユーザーのキャンセル分類をSecurityError、ConstraintError、DataErrorのような予期しないエラーとは別に扱ってください。
iOSのコード1005(NotInteractive)は、ASAuthorizationControllerでpreferImmediatelyAvailableCredentialsが設定されたときにデバイスで利用できるパスキーがなく、ユーザーにUIが表示されなかったことを意味します。これは、プライバシーの制約によりWebブラウザが提供できないクリーンな「このデバイスにはパスキーが存在しない」というシグナルです。Appleのメッセージは30以上の言語にローカライズされており、OSバージョン間で変更される可能性があるため、localizedDescriptionではなく、常に数値コードで分類してください。
条件付き作成中、NotAllowedError、AbortError、InvalidStateErrorはすべて想定内の結果であり、エラーとして表示するのではなく、静かに無視すべきです。NotAllowedErrorは自動入力が利用できないか、ページがフォーカスを失ったことを示し、InvalidStateErrorはプロバイダーにパスキーがすでに存在することを示します。呼び出しを試行する前に、getClientCapabilities()を使用してconditionalCreateのサポートを検証し、ドキュメントの表示状態を確認して、エラーのカウントが膨らむのを防いでください。
操作タイプ(条件付きUI、モーダルログイン、手動作成、条件付き作成、または自動追加)、操作開始からエラーまでの時間、OSバージョン、ブラウザバージョン、ハードウェアモデル、QR/ハイブリッドUIが表示されたかどうか、およびサーバー側のログと結合するための相関IDをキャプチャしてください。チャレンジの不一致、無効な署名、認証情報が見つからないなどのサーバー検証の失敗は、クライアント側のDOMException名と同じ分類に含めるのではなく、明示的な構造化されたコードとしてログに記録する必要があります。これらのシグナルを組み合わせることで、推測することなく、エラーの大部分をアクション可能な分類に分けることができます。
関連記事
目次