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 のフロー(およびその制限事項)

以前の SAA では、ユーザーが権限をすでに付与している場合でも、再読み込みのたびに 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 以外のリソースのサポート

ストレージ アクセス ヘッダーの更新により、iframe 以外の埋め込みコンテンツ(別のドメインでホストされている画像など)で SAA が有効になります。以前は、サードパーティ Cookie を使用できない場合、ブラウザで認証情報を使用してこのようなリソースを読み込むことを許可する Web Platform 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 を読み込むことができます。

ストレージ アクセス ヘッダーを使用すると、その後のページ訪問で次のフローが発生します。

  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. ユーザー エージェントは、ストレージ アクセス権限を使用して、パーティション分割されていない Cookie アクセスで iframe コンテンツを読み込みます。この手順を完了すると、ウィジェットが想定どおりに動作するようになります。
ストレージ アクセス ヘッダーのフローを示すフローチャート
ストレージ アクセス ヘッダーのフロー図。

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

ストレージ アクセス ヘッダー機能を使用する場合は、次の 2 つの場合にコードを更新する必要があります。

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

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

ソリューションでストレージ アクセス ヘッダーを使用するには、ソリューションを更新する必要があります。たとえば、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')
  }
});

このソリューションの実践的な仕組みについては、デモをご覧ください。

オリジン ヘッダーのロジックを更新する

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

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

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

主なメリット

SAA を使用する場合は、パフォーマンスが向上するストレージ アクセス ヘッダーを使用することをおすすめします。全体的に、この変更により次のような改善がもたらされます。

  • iframe 以外の埋め込みのサポート: より幅広いリソースで SAA を使用できるようになります。
  • ネットワーク使用量の削減: リクエスト数とペイロードが削減されます。
  • CPU 使用率の低減: JavaScript 処理が減ります。
  • UX の改善: 中断を伴う中間読み込みを排除します。

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

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

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

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

ローカルでテストする

ストレージ アクセス ヘッダー機能をローカルでテストして、ウェブサイトがこの変更に対応していることを確認できます。

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

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

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

フィードバックがある場合や問題が発生した場合は、問題を報告してください。ストレージ アクセス ヘッダーの詳細については、GitHub の説明をご覧ください。