代表的な面接トピック

フロントエンド面接:FedCM を用いたプライバシー保護型のフェデレーションサインインをどのように設計しますか?

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

質問

あるサイトで、サードパーティ Cookie やクロスサイトリダイレクトへの依存を減らしつつ、Google などのプロバイダによるサインインを実装する必要があります。RP、IdP、サーバー側での検証、フォールバック、およびサインアウトのフローを FedCM でどのように設計しますか?

プロンプトとコンテキスト

あなたは多言語対応サイトのエンタープライズサインインのエントリポイントを担当しています。プロダクト要件として、ユーザーが明確な選択を行った後にのみブラウザが ID プロバイダのアカウントを提示するようにし、プライバシー要件としてトラッキング目的のサードパーティ Cookie への依存を禁止しています。非対応ブラウザ、ユーザーによる拒絶、複数 IdP、セッション作成、サインアウトを含め、リライングパーティ(RP)、アイデンティティプロバイダ(IdP)、およびサーバー間の連携を設計してください。

面接官がテストしていること

優れた回答では、FedCM をトークン検証の代替ではなく、ブラウザが仲介するアイデンティティフェデレーションのインターフェースとして扱います。RP は navigator.credentials.get() でアイデンティティを要求し、ブラウザがアカウントの選択肢を表示し、IdP は短寿命のアサーションまたは認可結果を返します。サーバーはローカルセッションを作成する前に、署名、issuer、audience、nonce、state を引き続き検証します。また回答では、サードパーティ Cookie の制限、パーミッションポリシー、ユーザーの選択、および従来の OAuth/OIDC リダイレクトフォールバックを明確に区別する必要があります。

最初に確認すべき明確化のための質問

プロトコルと信頼モデル

IdP が OAuth、OIDC、またはカスタムアサーションのいずれを使用しているか、複数の IdP が許可されているか、サーバーが JWKS、issuer、audience の設定をどのように管理しているかを確認します。FedCM は IdP 境界における鍵ローテーションやトークン検証を代替するものではありません。

ブラウザとプライバシー要件

対象ブラウザ、埋め込み iframe、エンタープライズポリシー、および現在のサードパーティ Cookie の扱いを確認します。FedCM のサポート状況と UI の挙動はブラウザに依存するため、すべての環境で Chrome の挙動を前提にすることはできません。

アカウント連携とログアウトポリシー

1 つの外部 subject が 1 つのローカルアカウントにマップされるか、重複するメールアドレスをどう処理するか、グローバルログアウトで IdP に通知する必要があるか、リクエストが拒絶された場合にパスワードやメールサインインにフォールバック可能かを確認します。

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

「私は FedCM をブラウザ主導のアイデンティティ選択レイヤーとして扱います。RP はサーバーからワンタイムの state を取得し、navigator.credentials.get() を呼び出します。ブラウザが IdP アカウント選択画面を表示し、IdP はプロトコルにバインドされたアイデンティティ結果を返します。サーバーはサイトセッションを作成する前に、issuer、署名、audience、nonce、state、およびアカウントマッピングを検証します。非対応ブラウザ、パーミッションブロック、キャンセル、サーバー拒否はそれぞれ別の状態として扱います。フォールバックは CSRF 保護と PKCE を備えた OAuth/OIDC です。サインアウトはサイトのセッションと IdP のセッションを区別する必要があり、1 つの Cookie を削除してもグローバルログアウトにはなりません。」

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

ステップ 1: RP と IdP の設定

サーバーは、信頼できる各 IdP の issuer、クライアント ID、JWKS エンドポイント、許可されたプロトコル、コールバックポリシーを保存します。フロントエンドはサーバーが承認した設定識別子のみを受け取り、ユーザーからの任意の IdP URL は決して受け入れません。マルチテナント環境では、オープンリダイレクトやテナント間でのトークン配信を防ぐために、テナントごとに許可リストをバインドします。

ステップ 2: ワンタイムログイン状態の作成

ユーザーがサインインを開始した後、RP サーバーは予測不可能な state、nonce、およびブラウザセッション、テナント、リターンパスにバインドされた短寿命のフローレコードを作成します。フロントエンドはサーバーから提供されたパラメータを FedCM に送信します。state と nonce はサーバーが保持する使い捨ての値であり、フロントエンドで生成または再利用してはなりません。

ステップ 3: ブラウザを介したリクエストの実行

フロントエンドはセキュアコンテキストかつ必要なパーミッションポリシーのもとで navigator.credentials.get() を呼び出します。ブラウザはアカウント選択画面を表示し、ユーザーによる明示的な選択後にのみ処理を続行します。FedCM リクエストにはサーバーがアイデンティティフローを識別できるように専用の fetch destination が付与されます。フロントエンドは UI が表示されたことだけで認証成功とみなしてはなりません。

ステップ 4: サーバーでのアイデンティティ結果の検証

サーバーは issuer、署名、有効期限、audience、nonce、state、subject を検証し、明示的なポリシーを使用して外部アイデンティティをマッピングします。メールアドレスは補助的な属性であり、自動的なアカウント統合キーではありません。検証が完了して初めて、サーバーはサイトセッションを発行し、IdP、subject、認証時刻、および関連するリスクシグナルを記録します。

ステップ 5: フォールバックと失敗状態の設計

非対応ブラウザ、パーミッションブロック、ユーザーによるキャンセル、ネットワーク障害は個別に処理する必要があります。OAuth/OIDC リダイレクトのフォールバックでは、PKCE、完全一致するリダイレクト URI、state、nonce を使用し、同一のサーバー側アカウントマッピングレイヤーを経由して復帰します。UI は issuer、トークン、内部の検証エラーを露出させることなく、次のアクションを説明します。

ステップ 6: 複数 IdP とアカウント連携の処理

複数の IdP が許可されている場合、ページにはビジネスで承認されたリストが表示され、ブラウザと IdP がアカウント選択を完了します。サーバーは安定した外部キーとして (issuer, subject) を使用し、メールアドレスのみで暗黙的にマージすることはありません。IdP の追加には認証済みセッションまたはステップアップ検証が必要であり、監査可能な連携または連携解除イベントを生成します。

ステップ 7: ログアウト、取り消し、および段階的ロールアウト

サイトのログアウトでは、ローカルセッションを破棄し、セキュア Cookie をクリアし、リフレッシュトークンを無効化します。プロトコルと IdP がサポートしている場合は、クライアントから IdP のログアウトを呼び出すことも可能です。FedCM は Cookie に依存するすべてのログアウト機能を網羅しているわけではないため、サイトからのサインアウトとプロバイダからのサインアウトの違いを明確に説明します。ブラウザの対応状況やエラー率に応じて、可観測性のあるフォールバックスイッチを用意して段階的にロールアウトします。

質の高い回答例

私はブラウザによるアイデンティティ選択、IdP の証明、RP セッションの作成を分離します。RP サーバーは短寿命の state、nonce、テナントにバインドされたフローデータを作成します。フロントエンドはセキュアコンテキストで FedCM を開始し、ブラウザがアカウント選択画面を表示し、ユーザーの確認後に IdP が結果を返します。サーバーは issuer の JWKS 署名、audience、nonce、state、有効期限、subject を検証し、サイトセッションを作成する前に (issuer, subject) をローカルアカウントにマッピングします。

非対応ブラウザ、ポリシーブロック、キャンセル、ネットワーク障害は個別の状態として維持し、PKCE を備えた OAuth/OIDC にフォールバックします。フォールバックでも同一のサーバー検証および連携ポリシーを維持します。複数の IdP はサーバーの許可リストからのみ取得し、メールアドレスを自動マージキーとして使用しません。ログアウトはサイトセッションを無効化し、プロバイダのログアウトは別の機能としてユーザーに説明します。ロールアウト中は、ブラウザおよび IdP ごとに成功率、キャンセル率、フォールバック、アカウント連携の競合を監視し、エラーが増加した場合は FedCM エントリポイントのみを無効化できるスイッチを用意します。

よくある間違い

  • 間違い: FedCM の結果を認証済みセッションとして扱う。 → なぜ失敗するか: ブラウザを介した選択は issuer、署名、nonce を検証しないため。 → 修正方法: すべての結果を単一のサーバー検証およびセッション作成パスに通す。
  • 間違い: メールアドレスのみで既存のアカウントと照合する。 → なぜ失敗するか: メールアドレスは未検証であったり、再利用されたり、IdP 間で重複したりする可能性があるため。 → 修正方法: 外部キーとして (issuer, subject) を使用し、メールベースの連携には明示的な確認を要求する。
  • 間違い: FedCM の失敗後にフロントエンドのストレージにトークンを保存する。 → なぜ失敗するか: XSS のリスクを拡大し、既存のセッションポリシーをバイパスしてしまうため。 → 修正方法: サーバー側で結果を交換して保護されたセッション Cookie を設定させ、フロントエンドはステータスのみを処理する。
  • 間違い: サイトのログアウトによってユーザーが IdP からもログアウトされると思い込む。 → なぜ失敗するか: セッションのライフサイクルとプロトコル機能が異なるため。 → 修正方法: 各セッションを個別に無効化し、ログアウトの適用範囲を伝える。

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

フォローアップ 1: FedCM は通常の OAuth リダイレクトとどう関連しますか?

FedCM はブラウザがアカウント選択やクロスサイトでのやり取りを仲介する方法を変更しますが、認可とアイデンティティの証明は引き続き OAuth/OIDC が提供します。これらは issuer、nonce、state、PKCE、サーバー側のアカウントマッピングを共有できます。フォールバックでもこれらのチェックを削除してはなりません。

フォローアップ 2: なぜサードパーティ Cookie の制限がフェデレーションに影響するのですか?

埋め込まれた IdP は、これまでサードパーティ Cookie を使用してサインイン済みユーザーを識別していた場合があります。パーティション化またはブロックされた Cookie では、代わりにユーザーに見える形での明示的な選択が必要になります。FedCM は暗黙的なクロスサイト識別を減らしますが、アプリケーションの権限を決定するものではありません。

フォローアップ 3: 拒絶された IdP を別の IdP に暗黙的に置き換えることはできますか?

拒絶を暗黙の同意として扱ってはいけません。別の承認済み IdP またはパスワード入力を明示的なユーザーアクションとして提示し、完了したリクエストを再利用するのではなく、選択されたプロバイダ用に新しい state、nonce、フローデータを作成します。

フォローアップ 4: 段階的なロールアウトでサインインが損なわれていないことをどのように証明しますか?

成功、キャンセル、ポリシーブロック、フォールバック、アカウント競合、完了時間のメトリクスを、ブラウザ、IdP、地域、埋め込みコンテキストごとにセグメント化します。issuer の異常、署名の失敗、nonce のリプレイに対してアラートを設定します。確立された OAuth 検証パスを維持したまま、FedCM のみを無効化できるサーバー側スイッチを保持します。

公開情報ソース

関連する質問