プロンプトと適用されるコンテキスト
オフラインファーストのサイトにおいて、Service Worker でログイン Cookie の変更を検知し、キャッシュポリシーを更新する必要があります。サブスクリプションのスコープ、イベントのセマンティクス、競合状態、非対応ブラウザへのフォールバックを網羅した Cookie Store API のアプローチを設計してください。
Cookie Store API は非同期の Cookie の読み書きを提供し、Service Worker が一致する Cookie の変更をサブスクライブできるようにします。これはブロッキングが発生する document.cookie の代替手段となりますが、同一オリジンポリシー(same-origin)、path、Secure、HttpOnly、または SameSite の制約を変更するものではありません。
面接官が評価するポイント
ページ API と Service Worker サブスクリプション API の違い、cookiechange がスクリプトから参照可能な変更に関するものであるという事実、名前と URL によるフィルタリング、重複サブスクリプション、イベントの競合状態、そして Cookie がコンテキスト間で信頼できるデータベースではない理由を網羅してください。
確認のための質問
Cookie が HttpOnly であるかどうか、そのスコープがパスをまたぐかどうか、ページと Service Worker が同一オリジンであるかどうか、およびどのブラウザをサポートする必要があるかを確認します。ログイン、ログアウト、リフレッシュが競合する可能性があるか、キャッシュの変更を即時反映する必要があるか、オフライン時に古いセッション状態がどのくらいの期間許容されるかを尋ねます。
30秒の回答フレームワーク
「Service Worker 内で必要な Cookie 名と URL をサブスクライブし、cookiechange の発生後に関連する Cookie のみを再読み込みして、べき等なセッション状態マシンまたは単調増加するキャッシュバージョンを進めます。Cookie Store は非同期であり、イベントはスクリプトから参照可能な変更のみを対象とし、トランザクションやグローバルな順序性を提供しないため、ハンドラーは重複を排除して現在の状態を再読み込みする必要があります。非対応ブラウザではサーバー側の Cookie チェックと明示的なページ同期を維持します。古いキャッシュは決して認証の証明にはなりません。」
ステップバイステップの詳細解説
ステップ 1: API の境界を定義する
ページは window.cookieStore を介して非同期に読み書きできます。Service Worker は registration.cookies を通じてサブスクリプションを管理し、cookiechange を受信します。どちらも Cookie ポリシーに従い、HttpOnly の値を読み取ることはできません。
ステップ 2: 最小限のサブスクリプションを作成する
必要な Cookie 名のみをサブスクライブし、必要に応じて URL を制限します。異なるパスにある同じ名前の Cookie は共存できるため、ハンドラーは名前だけで推測するのではなく、イベント情報と現在の URL を使用して対象を特定する必要があります。
self.addEventListener("activate", (event) => {
event.waitUntil(
self.registration.cookies.subscribe([
{ name: "session", url: self.registration.scope },
]),
);
});ステップ 3: イベントをスナップショットではなく通知として扱う
イベントは Cookie の変更を記述しますが、非同期処理が実行される前に別の変更が発生する可能性があります。get() または getAll() で現在の状態を再読み込みし、処理をべき等にします。イベントオブジェクトをトランザクションログや確定した真実として扱ってはいけません。
ステップ 4: スクリプトから参照可能な変更と HttpOnly の変更を分離する
仕様では、スクリプトから参照可能な Cookie の変更に対する通知のみが要求されています。サーバーは Service Worker に値を公開することなく HttpOnly Cookie を設定または削除できます。認証の判定は依然としてサーバーのレスポンスに基づくものであり、イベントが発生しなかったことによるものではありません。
ステップ 5: セッションを明示的にモデル化する
unknown(不明)、verified(検証済み)、logged out(ログアウト済み)、expired(期限切れ)などの状態を使用し、レスポンスのバージョン、有効期限、または再検証結果に基づいて状態を進めます。Cookie の変更はチェックをトリガーするものであり、それ自体がログインまたはログアウトを証明するものではありません。
ステップ 6: タブ間の競合状態を処理する
複数のページが同時に Cookie をリフレッシュまたは削除する可能性があります。短時間のバーストを結合(coalesce)し、最新の読み取りから 1 つのキャッシュ更新を適用し、古いイベントが新しい状態を上書きできないようにセッションバージョンを使用します。キャッシュの削除と事前キャッシュ(precaching)もべき等にする必要があります。
ステップ 7: 非対応ブラウザ用のフォールバックを設計する
Cookie Store が利用できない場合は、サーバーを信頼できる情報源(authoritative)としつつ、重要なナビゲーションやネットワークレスポンスの後に明示的な同期を実行します。HttpOnly の値を取得するために document.cookie をポーリングしたり、API が存在しないからといってキャッシュの認証を緩めたりしてはいけません。
ステップ 8: プライバシーとセキュリティの露出を最小限に抑える
ビジネス上必要な名前と URL のみをサブスクライブします。Cookie の値をログ、Cache Storage、または postMessage に決して書き込まないでください。Secure、HttpOnly、SameSite、Path、および適切な有効期限設定を維持し、ログアウト時にクライアントキャッシュをクリアします。
質の高い模範解答
私は Cookie Store を認証データベースとしてではなく、変更通知機能として使用します。Service Worker のアクティベーション中に、正確な名前とスコープに対してべき等なサブスクリプションを作成します。cookiechange の受信時には、スクリプトから参照可能な現在の状態を再読み込みし、べき等なセッション状態マシンを進め、セッションバージョンを使用してキャッシュを更新またはクリアします。HttpOnly の値は引き続きサーバー側で検証され、イベントがないことはセッションが不変であることを証明するものではありません。複数のタブからの同時リフレッシュを結合し、古い通知が新しい状態を上書きしないようにします。非対応ブラウザでは、重要なリクエストに対してサーバー検証を維持し、明示的なページ同期を使用します。HttpOnly 保護の代替として document.cookie のポーリングを使用することは決してありません。サブスクリプションとキャッシュ操作のスコープを適切に設定し、ログアウト、有効期限切れ、オフライン利用、および Service Worker のアップデートをテストします。
よくある間違い
cookiechange を完全な監査ログとして扱うこと
これは通知であり、プロセスをまたぐトランザクションシーケンスではありません。ハンドラーは現在の状態を再読み込みし、重複した処理を許容する必要があります。
Service Worker が HttpOnly Cookie を読み取れると思い込むこと
HttpOnly は依然としてスクリプトによる読み取りをブロックします。Service Worker はリクエストを通じてサーバーにセッションの検証を依頼できますが、Cookie Store がその秘密の値を明かすことはありません。
任意の Cookie の変更でキャッシュの認証を決定してしまうこと
変更はリフレッシュ、有効期限切れ、または別のパスから生じる可能性があります。認証に影響するキャッシュを変更する前に、サーバーの検証とバージョンの状態を待つ必要があります。
フォローアップの質問と回答
別のパスにある同じ名前の異なる Cookie を誤って削除しないようにするにはどうすればよいですか?
サブスクリプションおよび読み取り時に URL スコープを保持し、正確な名前、URL、Path、およびその他の属性を指定して削除します。ターゲットを特定できない場合は、広範な削除を実行するのではなく、サーバーのレスポンスでクリーンアップを実行するようにします。
Service Worker のアップデートによってサブスクリプションが失われることはありますか?
新しいワーカーの activate フェーズ中に、サブスクリプションが存在することをべき等に確認し、現在の Cookie 状態を再読み込みしてキャッシュを再構築します。古いワーカーのメモリに依存してはいけません。初期化はアップデート後に実行される必要があります。
オフラインで Cookie の有効期限が切れ、ネットワークがない場合はどうなりますか?
ローカルの状態を未検証(unverified)としてマークし、オフライン機能を制限します。オフラインモードでサーバーセッションを延長することはできません。接続が復帰した際にまず再検証を行い、その後にキャッシュを復元、クリア、またはダウングレードします。