Storage Access での HTTP ヘッダー サポートの送信元トライアル

Natalia Markoborodova
Natalia Markoborodova

Chrome は、バージョン 130 で Storage Access API(SAA)に HTTP ヘッダーを追加するオリジン トライアル(Storage Access Headers)を開始します。新しい Sec-Fetch-Storage-Access リクエスト ヘッダーと Activate-Storage-Access レスポンス ヘッダーは、iframe 以外のリソースをサポートし、ソーシャル メディア ウィジェット、カレンダー、インタラクティブ ツールなどの埋め込みコンテンツに依存するウェブサイトのパフォーマンスとユーザー エクスペリエンスを向上させることを目的としています。

JavaScript フロー(およびその制限事項)

以前は、ユーザーがすでに権限を付与している場合でも、リロードのたびに document.requestStorageAccess() への JavaScript API 呼び出しが必要でした。この方法は効果的ですが、次のような制限があります。

  • 複数のネットワーク ラウンド トリップ: 埋め込みコンテンツが完全に機能するまでに、複数のネットワーク リクエストとページ再読み込みが必要になることがよくありました。
  • iframe の依存関係: JavaScript の実行では、iframe 内の iframe またはサブリソースの使用が義務付けられていたため、デベロッパーの柔軟性が制限されていました。

たとえば、JavaScript のみを使用して website.example に埋め込まれた calendar.example のカレンダー ウィジェットは次のようになります。

  1. プレースホルダを読み込む: website.example がウィジェットをリクエストします。website.example に埋め込まれた calendar.example ウィジェットは、パーティション分割されていない Cookie にアクセスできないため、代わりにプレースホルダ ウィジェットがレンダリングされます。
  2. 権限をリクエストする: プレースホルダが読み込まれ、document.requestStorageAccess() を呼び出して storage-access 権限をリクエストします。
  3. ユーザーが権限を付与することを選択します。
  4. ウィジェットを再読み込みする: ウィジェットが更新され、今度は Cookie にアクセスして、パーソナライズされたコンテンツが読み込まれます。
  5. ユーザーが calendar.example ウィジェットを埋め込んだサイトに再度アクセスするたびに、フローはステップ 1、24 とまったく同じになります。簡略化されるのは、ユーザーがアクセス権を再度付与する必要がないことだけです。

このフローは非効率的です。ユーザーがすでにストレージ権限を付与している場合、最初の iframe の読み込み、document.requestStorageAccess() 呼び出し、その後の再読み込みは不要になり、レイテンシが発生します。

HTTP ヘッダーを使用した新しいフロー

新しいストレージ アクセス ヘッダーにより、iframe 以外のリソースを含む埋め込みコンテンツをより効率的に読み込むことができます。

ストレージ アクセス ヘッダーを使用すると、ユーザーがすでに権限を付与している場合、ブラウザは Sec-Fetch-Storage-Access: inactive リクエスト ヘッダーが設定されたリソースを自動的に取得します。リクエスト ヘッダーを設定するためにデベロッパー側で必要な対応はありません。サーバーは Activate-Storage-Access: retry; allowed-origin="<origin>" ヘッダーで応答できます。ブラウザは必要な認証情報を使用してリクエストを再試行します。

リクエスト ヘッダー

Sec-Fetch-Storage-Access: <access-status>

ユーザーがクロスサイト コンテンツが埋め込まれたページにアクセスすると、ブラウザは認証情報(Cookie など)が必要になる可能性のあるクロスサイト リクエストに Sec-Fetch-Storage-Access ヘッダーを自動的に含めます。このヘッダーは、埋め込みの Cookie アクセス権限のステータスを示します。値の解釈方法は次のとおりです。

  • none: 埋め込みに storage-access 権限がないため、パーティション分割されていない Cookie にアクセスできません。
  • inactive: 埋め込みには storage-access 権限がありますが、その使用をオプトインしていません。埋め込みにパーティショニングされていない Cookie へのアクセス権がない。
  • active: 埋め込みにパーティショニングされていない Cookie へのアクセス権がある。この値は、パーティション分割されていない Cookie にアクセスできるクロスオリジン リクエストに含まれます。

レスポンス ヘッダー

Activate-Storage-Access: <retry-or-reload>

Activate-Storage-Access ヘッダーは、Cookie を使用してリクエストを再試行するか、SAA を有効にしてリソースを直接読み込むようにブラウザに指示します。ヘッダーには次の値を指定できます。

  • load: ブラウザに対し、リクエストされたリソースのパーティション分割されていない Cookie へのアクセス権を埋め込み元に付与するよう指示します。
  • retry: サーバーは、ブラウザがストレージ アクセス権限を有効にしてからリクエストを再試行するよう応答します。
Activate-Storage-Access: retry; allowed-origin="https://site.example"
Activate-Storage-Access: retry; allowed-origin=*
Activate-Storage-Access: load

非 iframe リソースのサポート

Storage Access Headers の更新により、別のドメインでホストされている画像など、iframe 以外の埋め込みコンテンツで SAA が有効になります。これまで、サードパーティ Cookie が利用できない場合、ブラウザで認証情報を使用してこのようなリソースを読み込むことを許可するウェブ プラットフォーム API はありませんでした。たとえば、embedding-site.example は次のように画像をリクエストできます。

   <img src="https://server.example/image"/>

サーバーは、Cookie が利用可能かどうかに応じて、コンテンツまたはエラーで応答できます。

app.get('/image', (req, res) => {
  const headers = req.headers;
  const cookieHeader = headers.cookie;
  // Check if the embed has the necessary cookie access
  if (!cookieHeader || !cookieHeader.includes('foo')) {
  // If the cookie is not present, check if the browser supports Storage Access headers
    if (
      'sec-fetch-storage-access' in headers &&
      headers['sec-fetch-storage-access'] == 'inactive'
    ) {
    // If the browser supports Storage Access API, retry the request with storage access enabled
      res.setHeader('Activate-Storage-Access', 'retry; allowed-origin="https://embedding-site.example"');
    }
    res.status(401).send('No cookie!');
   } else {
    // If the cookie is available, check if the user is authorized to access the image
    if (!check_authorization(cookieHeader)) {
      return res.status(401).send('Unauthorized!');
    }
    // If the user is authorized, respond with the image file
    res.sendFile("path/to/image.jpeg");
  }
});

Cookie が利用できない場合、サーバーは Sec-Fetch-Storage-Access リクエスト ヘッダーの値を確認します。この値が inactive に設定されている場合、サーバーは Activate-Storage-Access: retry ヘッダーで応答し、リクエストをストレージ アクセスで再試行する必要があることを示します。Cookie が存在せず、Sec-Fetch-Storage-Access ヘッダーの値が inactive でない場合、画像は読み込まれません。

HTTP ヘッダーのフロー

HTTP ヘッダーを使用すると、ブラウザはユーザーがウィジェットにストレージ アクセス権限をすでに付与していることを認識し、以降のアクセス時にパーティション分割されていない Cookie にアクセスできる iframe を読み込むことができます。

Storage Access Headers を使用すると、後続のページにアクセスしたときに次のフローがトリガーされます。

  1. ユーザーが calendar.example が埋め込まれた website.example に再度アクセスします。このフェッチは、以前と同様にまだ Cookie にアクセスできません。ただし、ユーザーは以前に storage-access 権限を付与しており、フェッチには Sec-Fetch-Storage-Access: inactive ヘッダーが含まれています。これは、パーティション分割されていない Cookie へのアクセスは可能だが、使用されていないことを示します。
  2. calendar.example サーバーは、Activate-Storage-Access: retry; allowed-origin="<origin>" ヘッダー(この場合、<origin>https://website.example になります)で応答し、リソースの取得にはストレージ アクセス権限を持つパーティション分割されていない Cookie の使用が必要であることを示します。
  3. ブラウザはリクエストを再試行します。今回はパーティション化されていない Cookie も含めます(このフェッチの storage-access 権限を有効にします)。
  4. calendar.example サーバーは、パーソナライズされた iframe コンテンツを返します。レスポンスには Activate-Storage-Access: load ヘッダーが含まれます。これは、ブラウザが storage-access 権限を有効にしてコンテンツを読み込む(つまり、document.requestStorageAccess() が呼び出されたかのように、パーティション分割されていない Cookie アクセスで読み込む)必要があることを示します。
  5. ユーザー エージェントは、storage-access 権限を使用して、パーティション分割されていない Cookie アクセスで iframe コンテンツを読み込みます。この手順を完了すると、ウィジェットが想定どおりに動作するようになります。
ストレージ アクセス ヘッダーのフローを示すフローチャート。
Storage Access Header のフロー図。

ソリューションを更新する

Storage Access Headers 機能を使用する場合、次の 2 つのケースでコードの更新が必要になることがあります。

  1. SAA を使用しており、ヘッダー ロジックでパフォーマンスを向上させたい。
  2. サーバーで、リクエストに Origin ヘッダーが含まれているかどうかに依存する検証またはロジックがある。

SAA ヘッダー ロジックを実装する

ソリューションで Storage Access Headers を使用するには、ソリューションを更新する必要があります。calendar.example のオーナーであるとします。website.example がパーソナライズされた calendar.example ウィジェットを読み込めるようにするには、ウィジェット コードにストレージ アクセス権が必要です。

クライアントサイド

ストレージ アクセス ヘッダー機能では、既存のソリューションでクライアント側のコードを更新する必要はありません。SAA を実装する方法については、ドキュメントをご覧ください。

サーバーサイド

サーバー側では、次の新しいヘッダーを使用できます。

app.get('/cookie-access-endpoint', (req, res) => {
  const storageAccessHeader = req.headers['sec-fetch-storage-access'];

  if (storageAccessHeader === 'inactive') {
    // User needs to grant permission, trigger a prompt
    if (!validate_origin(req.headers.origin)) {
      res.status(401).send(`${req.headers.origin} is not allowed to send` +
          ' credentialed requests to this server.');
      return;
    }
    res.set('Activate-Storage-Access', `retry; allowed-origin="${req.headers.origin}"`);
    res.status(401).send('This resource requires storage access. Please grant permission.');
  } else if (storageAccessHeader === 'active') {
    // User has granted permission, proceed with access
    res.set('Activate-Storage-Access', 'load');
    // Include the actual iframe content here
    res.send('This is the content that requires cookie access.');
  } else {
    // Handle other cases (e.g., 'Sec-Fetch-Storage-Access': 'none')
  }
});

デモで、このソリューションの実際の動作をご確認ください。

Origin ヘッダーのロジックを更新する

Storage Access Headers を使用すると、Chrome は以前よりも多くのリクエストで Origin ヘッダーを送信します。サーバーサイドのロジックが、特定のタイプのリクエスト(CORS で定義されたリクエストなど)にのみ Origin ヘッダーが存在することを前提としている場合、この変更が影響する可能性があります。

潜在的な問題を回避するには、サーバーサイド コードを確認する必要があります。

  • Origin ヘッダーの存在に依存する検証やロジックがないか確認します。
  • より多くのケースで Origin ヘッダーが存在する場合に対応するようにコードを更新します。

主なメリット

Storage Access Headers は、SAA を使用するうえで推奨される、よりパフォーマンスの高い方法です。この変更により、次のような改善が実現します。

  • iframe 以外の埋め込みのサポート: より広範なリソースで SAA を有効にします。
  • ネットワーク使用量の削減: リクエストの減少とペイロードの縮小。
  • CPU 使用率の低下: JavaScript の処理が減少します。
  • UX の改善: 中間負荷の発生を抑制します。

オリジン トライアルに参加する

オリジン トライアルでは、新機能を試して、その使いやすさ、実用性、有効性についてフィードバックを送信できます。詳しくは、オリジン トライアルを使ってみるをご覧ください。

Storage Access Headers 機能は、Chrome 130 以降のオリジン トライアルに登録することで試すことができます。オリジン トライアルに参加するには:

  1. Storage Access Headers のオリジン トライアルの登録ページに移動します。
  2. オリジン トライアルへの参加に関する手順に沿って操作します。

ローカルでテストする

Storage Access Headers 機能はローカルでテストして、ウェブサイトがこの変更に対応していることを確認できます。

Chrome インスタンスを構成する手順は次のとおりです。

  1. chrome://flags/#storage-access-headers で Chrome フラグを有効にします。
  2. 変更を反映させるには、Chrome を再起動します。

意見交換とフィードバックの提供

フィードバックがある場合や問題が発生した場合は、問題をご提出ください。Storage Access Headers の詳細については、GitHub の説明をご覧ください。