代表的な面接トピック

フロントエンド面接: WebAuthn conditional create を安全にロールアウトするには?

フロントエンド難しい
Offer.cc 編集チーム公開日 更新日

質問

既存のパスワードログインページでユーザーがアカウントを入力している最中に、ブラウザがパスキーの作成を提案するようにしたいと考えています。機能検出、サーバー検証、およびフォールバックをどのように設計しますか?

プロンプトと適用されるコンテキスト

プロダクトはすでにユーザー名/パスワードログインと、パスキーサインイン用の conditional get をサポートしています。信頼度の高いログインの後に WebAuthn Level 3 conditional create を使用し、フローを中断することなくパスキーの作成を提案したいと考えています。ブラウザの機能検出、作成ゲート、サーバー検証、プライバシー境界、およびロールバックについて説明してください。

これは Web プラットフォームと認証 UX に焦点を当てています。ブラウザ API がサポートされているからといって、デバイスに使用可能な認証器があるとは限りません。作成には依然としてユーザーの同意とサーバー検証が必要です。

面接官が評価するポイント

  • conditional create、conditional get、およびボタン押下による明示的な作成を区別できているか。
  • 機能、ポリシー、アカウント状態、クロスデバイス同期を明確なゲートとして結び付けられているか。
  • 重複する認証情報、アカウントの誤バインド、認証情報存在の漏洩、パスワードログインの阻害を防げているか。
  • 新しい API を一律に有効化するのではなく、カナリアリリースおよび機能の取り下げができるか。

優れた回答では、conditional create を段階的な拡張として扱います。非対応、キャンセル、またはタイムアウトした試行があってもメインフローは変更されず、サーバーは引き続き challenge、origin、RP ID、およびアカウントバインドを検証します。

回答前の確認質問

  1. 対象はサインインしているすべてのユーザーですか、それともメール確認済み、MFA 済み、または最近高リスクの再認証を完了したユーザーのみですか?
  2. マルチデバイスで同期されるパスキーは許可されますか?これによりリカバリおよび失効の要件が変わります。
  3. ページ上で保留中の credentials.create() リクエストがすでに存在する可能性はありますか?リクエストが競合するとプロンプトの挙動が予測できなくなります。
  4. conditional create が利用できない場合、「パスキーを作成」ボタンを明示的に表示すべきですか、それとも機能を非表示にすべきですか?

30秒の回答フレームワーク

「conditional-create の機能を検出した上で、アカウント状態、直近の認証強度、およびサーバーのフィーチャーフラグを組み合わせてから試行します。クライアントはユーザーが明示的に承認したタイミングで最大1つのリクエストを開始し、AbortController で重複をキャンセルします。非対応、キャンセル、またはタイムアウトした試行は元のフローに戻ります。サーバーは使い捨ての challenge をユーザー、origin、RP ID、有効期限にバインドし、検証後にのみ認証情報を保存します。カナリア中には、作成成功率、キャンセル、重複認証情報、パスワードフォールバック、およびリカバリチケットを追跡します。インシデント発生時はフラグを無効化します。既存の認証情報は引き続き使用または個別に失効できます。」

ステップバイステップの詳細な回答

1. 2つの条件付きインタラクションを分離する

conditional get は、ユーザーがアカウントを入力中に既存のパスキーを選択できるようにします。conditional create は、フォームのコンテキスト内で新しい認証情報の登録を提案します。どちらもブラウザと認証器の機能に依存するため、PublicKeyCredential オブジェクトの存在を確認するだけでは不十分です。

機能検出は試行するかどうかを決定するものであり、承認するかどうかを決めるものではありません。サーバーは登録を現在認証されているユーザーにバインドし、作成元とポリシーバージョンを記録し続ける必要があります。

2. 作成ゲートを定義する

次のすべてを必須とします:ブラウザが conditional-create 機能を報告していること、ユーザーが直近で十分な認証を完了していること、アカウントがリカバリ、マージ、または高リスクな変更の途中でないこと、そしてサーバーフラグがテナントおよびトラフィック枠を有効にしていること。新しいデバイスでは、ページ読み込み時に作成するのではなく、利点を説明してユーザーがそのまま続行できるようにします。

3. 重複と競合状態を防ぐ

ページセッションごとに1つの作成リクエストのみを許可します。別のリクエストを開始する前に前のリクエストをキャンセルし、コンポーネントがアンマウントされたときにもキャンセルします。サーバーの challenge は使い捨てとし、credential ID には一意性制約を設け、重複した送信には別の行を作成するのではなく冪等な結果を返します。

text
capability -> policy gate -> one challenge -> user consent
      |            |               |
   fallback   feature flag     server verify -> persist

4. 登録を完全に検証する

サーバーは challenge、origin、RP ID、署名、user handle、アテステーションポリシー、および credential ID を検証します。クライアント側の「作成成功」という結果を決して信用してはいけません。デバイスアテステーションが不要な場合は、よりシンプルなアテステーションポリシーを選択し、プライバシーとリスクのトレードオフを明記します。

5. 同期とリカバリを処理する

同期されたパスキーはユーザーがデバイスを変更した後に表示される場合がありますが、同期はアカウントリカバリではありません。認証情報リスト、単一認証情報の失効機能、およびすべてのデバイスを紛失したユーザー向けのリカバリパスを提供します。未認証のリクエストに対してパスキーの存在を明かしてはなりません。

6. 有用なテレメトリを用いたカナリアリリース

ブラウザ、プラットフォーム、テナント、リスクレベルごとに有効化します。機能検出、プロンプト表示、同意、検証失敗、キャンセル/タイムアウト、重複認証情報、パスワードフォールバック、およびサポートチケットを記録します。「非対応」と「ユーザーによる拒否」を分離します。そうでなければ、文言を改善すべきか機能を無効化すべきかを判断できません。

7. アカウントを壊さずにロールバックする

リモートフラグを使用して既存のパスキーログインを維持しながら、新規作成の試行を停止します。リリースのロールバックの一環として認証情報を削除してはなりません。失効はアカウント操作です。古い challenge バージョンに対して期限付きの互換性ウィンドウを維持し、動作が変更された際にはブラウザと認証器のテストを再実行します。

質の高い回答例

conditional create を可逆的な機能拡張として導入します。クライアントは機能を検出した後、アカウント状態、直近の認証強度、フィーチャーフラグを確認します。1ページあたり1つのリクエストを強制し、AbortController で重複をキャンセルします。サーバーは使い捨ての challenge を作成し、永続化の前に challenge、origin、RP ID、署名、credential ID を検証します。非対応、キャンセル、またはタイムアウトした試行はパスワードログインに戻り、ログインの失敗としては扱いません。プラットフォームおよびリスクごとにカナリアを実施し、機能、同意、検証エラー、重複認証情報、フォールバック、リカバリチケットを追跡します。フラグを無効化すると新規作成は停止しますが、既存のパスキーと失効機能は引き続き利用可能です。

よくある間違い

  • 間違い → PublicKeyCredential が存在するかどうかのみを確認する → オブジェクトが存在しても conditional create や認証器が利用可能であることの証明にはなりません。修正策: 機能検出を使用し、フォールバックを維持します。
  • 間違い → ページ読み込み時に暗黙的に create を呼び出す → ユーザーが同意しておらず、重複プロンプトが発生しやすくなります。修正策: 明示的な信頼度の高いタイミングでトリガーし、ユーザーが続行できるようにします。
  • 間違い → クライアント側の成功結果を信頼する → challenge、origin、またはアカウントバインドが未検証の可能性があります。修正策: サーバー側で登録検証を完結させます。
  • 間違い → ロールバック時に新しい認証情報を削除する → リリースのロールバックがアカウントの破壊につながります。修正策: 新規作成を無効化し、失効は個別に管理します。

フォローアップの質問と回答

ユーザーが拒否した後、毎日プロンプトを表示すべきですか?

いいえ。ローカルのクールダウンとポリシーバージョンを記録します。アカウントのリスク、デバイス、またはプロダクトの状況が大幅に変化した場合にのみ再確認します。拒否してもパスワードログインに影響を与えてはなりません。

同じアカウントに同一の credential ID を持つ行が2つ存在する場合はどうしますか?

credential ID を一意にし、登録を冪等にして、登録元を記録します。重複がすでに存在する場合は、新規書き込みを凍結し、ユーザーおよび credential ID ごとにマージまたは確認します。暗黙的に上書きしてはなりません。

機能はサポートされているのに成功率が急落しました。最初に何を調査しますか?

ブラウザのバージョン、プラットフォーム、認証器、エラーコードでスライスし、キャンセル、タイムアウト、ポリシー拒否、サーバー検証失敗を切り分けます。影響を受けるフラグコホートを一時停止し、パスワードおよび既存のパスキーログインを維持したまま原因を修正し、小規模なコホートで再検証します。

公開情報ソース

関連する質問