関連ウェブサイト セット: デベロッパー ガイド

関連ウェブサイト セット(RWS)は、ブラウザが複数のドメイン間の関係を把握するのに役立つウェブ プラットフォーム メカニズムです。これにより、ブラウザはサイトの特定の機能(クロスサイト Cookie へのアクセスを許可するかどうかなど)を有効にし、この情報をユーザーに提示するための重要な決定を下すことができます。

Chrome でサードパーティ Cookie が廃止されるのに伴い、ウェブにおける主要なユースケースを維持しながら、ユーザーのプライバシーを向上させることを目指しています。たとえば、多くのサイトでは、単一のユーザー エクスペリエンスを提供するために複数のドメインに依存しています。組織では、国別のドメインやサービス ドメインなど、複数のユースケースで異なるトップレベル ドメインを維持して画像や動画をホストすることが必要な場合があります。関連ウェブサイト セットを使用すると、サイトは固有の設定でドメイン間でデータを共有できます。

大まかに言うと、関連ウェブサイト セットはドメインの集まりで、1 つの「セット プライマリ」と場合によっては複数の「セット メンバー」が含まれます。

次の例では、primary はプライマリ ドメインを示し、associatedSites関連するサブセットの要件を満たすドメインを一覧表示します。

{
  "primary": "https://primary.com",
  "associatedSites": ["https://associate1.com", "https://associate2.com", "https://associate3.com"]
}

正規の関連ウェブサイト セットリストは、関連ウェブサイト セット GitHub リポジトリでホストされている JSON ファイル形式の一般公開リストで、すべてのセットの信頼できる情報源として機能します。Chrome はこのファイルを使用して動作を適用します。

ドメインに対する管理者権限を持つユーザーのみが、そのドメインでセットを作成できます。送信者は、各「set member」と「set primary」の関係を宣言する必要があります。集合のメンバーには、さまざまなドメインタイプの範囲を含めることができ、ユースケースに基づくサブセットの一部である必要があります。

アプリケーションが、同じ関連ウェブサイト セット内のサイト間でクロスサイト Cookie(サードパーティ Cookie)へのアクセスに依存している場合は、Storage Access API(SAA)requestStorageAccessFor API を使用して、これらの Cookie へのアクセスをリクエストできます。各サイトが属しているサブセットに応じて、ブラウザは異なる方法でリクエストを処理できます。

セットを登録するプロセスと要件について詳しくは、送信ガイドラインをご覧ください。送信されたセットは、さまざまな技術的チェックを経て検証されます。

関連ウェブサイト セットは、組織が複数のトップレベル サイト間で共有 ID の形式を必要とする場合に適しています。

関連ウェブサイト セットのユースケースには、次のようなものがあります。

  • 国のカスタマイズ。共有インフラストラクチャに依存しながらローカライズされたサイトを活用する(example.co.uk は example.ca でホストされるサービスに依存する場合があります)。
  • サービス ドメインの統合。ユーザーが直接やり取りすることのないサービス ドメインを活用しながら、同じ組織のサイト間でサービスを提供するサービスドメイン(example-cdn.com)
  • ユーザー コンテンツの分離。認証(およびその他の)Cookie へのサンドボックス ドメイン アクセスを許可すると同時に、セキュリティ上の理由から、ユーザーがアップロードしたコンテンツと他のサイトのコンテンツを分離するさまざまなドメインのデータにアクセスする。非アクティブなユーザーがアップロードしたコンテンツを配信する場合は、ベスト プラクティスに沿って同じドメインで安全にホストすることもできます。
  • 認証済みコンテンツの埋め込み。アフィリエイトのプロパティ(最上位サイトにログインしたユーザーのみに制限された動画、ドキュメント、リソース)の埋め込みコンテンツをサポートする。
  • ログイン。関連するプロパティ間でのログインをサポートします。ユースケースによっては、FedCM API も適切な場合があります。
  • 分析。アフィリエイト プログラムでのユーザー ジャーニーの分析と測定を実施して、サービスの品質を向上させる。

Storage Access API

対応ブラウザ

  • 119
  • 85
  • 65
  • 11.1

ソース

Storage Access API(SAA)は、埋め込まれたクロスオリジン コンテンツが、通常はファーストパーティのコンテキストでのみアクセスされるストレージにアクセスする方法を提供します。

埋め込みリソースは、SAA メソッドを使用して、現在ストレージにアクセスできるかどうかを確認し、ユーザー エージェントにアクセスをリクエストできます。

サードパーティの Cookie がブロックされていて、関連ウェブサイト セット(RWS)が有効になっている場合、Chrome は RWS 内のコンテキストで権限を自動的に付与し、それ以外の場合はユーザーにプロンプトを表示します。(「RWS 内コンテキスト」とは、埋め込みサイトとトップレベル サイトが同じ RWS 内にある iframe などのコンテキストのことです)。

ストレージへのアクセス権を確認してリクエストする

現在ストレージにアクセスできるかどうかを確認するには、埋め込みサイトで Document.hasStorageAccess() メソッドを使用します。

このメソッドは、ドキュメントがすでに Cookie にアクセスできるかどうかを示すブール値で解決される Promise を返します。iframe がトップフレームと同じオリジンの場合も、Promise は true を返します。

クロスサイト コンテキストで Cookie へのアクセスをリクエストする場合は、埋め込みサイトで Document.requestStorageAccess()(rSA)を使用できます。

requestStorageAccess() API は、iframe 内から呼び出すことを想定しています。この iframe ではユーザー操作(すべてのブラウザで必要なユーザー操作)を受け取ったばかりである必要があり、さらに Chrome では、ユーザーが過去 30 日間のどこかの時点で、ユーザーがその iframe を所有するサイトにアクセスし、特に(iframe 内ではなくトップレベルのドキュメントとして)そのサイトを操作していることが必要になります。

requestStorageAccess() は、ストレージへのアクセスが許可されている場合に解決される Promise を返します。なんらかの理由でアクセスが拒否された場合、Promise はその理由を引用して拒否されます。

Chrome の requestStorageAccessFor

対応ブラウザ

  • 119
  • 119
  • x
  • x

ソース

Storage Access API は、埋め込みサイトがユーザー操作を行った <iframe> 要素内からストレージへのアクセスをリクエストすることのみを許可します。

このため、Cookie を必要とするクロスサイト画像やスクリプトタグを使用するトップレベル サイトに Storage Access API を導入する際に課題が生じます。

これに対処するために、Chrome では、トップレベル サイトが Document.requestStorageAccessFor()(rSAFor)を使用して特定のオリジンの代わりにストレージ アクセスをリクエストする方法を実装しました。

 document.requestStorageAccessFor('https://target.site')

requestStorageAccessFor() API は、トップレベルのドキュメントによって呼び出されることを想定しています。また、このドキュメントには、ユーザーとのやり取りが発生したばかりであることも必要です。ただし、requestStorageAccess() とは異なり、Chrome は過去 30 日以内に最上位ドキュメントでのインタラクションを確認しません。ユーザーはすでにページを表示しているためです。

ストレージのアクセス権限を確認する

カメラや位置情報など、一部のブラウザ機能へのアクセスは、ユーザーが許可した権限に基づきます。Permissions API では、API へのアクセスに関する権限のステータス(付与、拒否、なんらかのユーザー操作(プロンプトのクリックやページ操作など)が必要)を確認できます。

navigator.permissions.query() を使用して権限のステータスをクエリできます。

現在のコンテキストに対するストレージ アクセス権限を確認するには、'storage-access' 文字列を渡す必要があります。

navigator.permissions.query({name: 'storage-access'})

指定した送信元のストレージ アクセス権限を確認するには、'top-level-storage-access' 文字列を渡す必要があります。

navigator.permissions.query({name: 'top-level-storage-access', requestedOrigin: 'https://target.site'})

なお、埋め込み元の整合性を保護するため、document.requestStorageAccessFor を使用して最上位のドキュメントによって付与される権限のみがチェックされます。

権限を自動的に付与できるかどうか、またはユーザー操作を必要とするかどうかに応じて、prompt または granted を返します。

フレームモデルごと

rSA 権限はフレームごとに適用されます。rSA 権限と rSAFor 権限は、別々の権限として扱われます。

新しいフレームごとにストレージへのアクセスを個別にリクエストする必要があり、自動的にアクセス権が付与されます。最初のリクエストのみがユーザー操作を必要とし、iframe によって開始される後続のリクエスト(ナビゲーションやサブリソースなど)は、最初のリクエストによってブラウジング セッションに付与されるため、ユーザー操作を待機する必要はありません。

更新、再読み込み、またはその他の方法で iframe を再作成する場合は、再度アクセスをリクエストする必要があります。

rSA では、クロスサイト コンテキストで使用するようにマークされている Cookie へのアクセスのみが提供されるため、Cookie では SameSite=None 属性と Secure 属性の両方を指定する必要があります。

SameSite=Lax または SameSite=Strict が指定されている、または SameSite 属性がない Cookie は、ファーストパーティでのみ使用され、rSA に関係なくクロスサイト コンテキストで共有されることはありません。

セキュリティ

rSAFor の場合、サブリソース リクエストにはクロスオリジン リソース シェアリング(CORS)ヘッダーまたはリソースの crossorigin 属性が必要です。これにより、明示的にオプトインできます。

実装の例

埋め込みクロスオリジン iframe からストレージへのアクセスをリクエストする

toplevel.site に埋め込まれたサイトを示す図
別のサイトの埋め込みで requestStorageAccess() を使用する

ストレージへのアクセス権があるかどうかを確認する

ストレージへのアクセス権がすでに付与されているかどうかを確認するには、document.hasStorageAccess() を使用してください。

Promise が true に解決されると、クロスサイト コンテキストでストレージにアクセスできます。false と解決された場合は、ストレージ アクセスをリクエストする必要があります。

document.hasStorageAccess().then((hasAccess) => {
    if (hasAccess) {
      // You can access storage in this context
    } else {
      // You have to request storage access
    }
});

ストレージへのアクセス権をリクエストする

ストレージ アクセスをリクエストする必要がある場合は、まずストレージ アクセス権限 navigator.permissions.query({name: 'storage-access'}) をチェックして、ユーザー操作が必要かどうか、または自動的に付与できるかどうかを確認します。

権限が granted の場合は、document.requestStorageAccess() を呼び出すと、ユーザー操作なしで成功するはずです。

権限のステータスが prompt の場合は、ボタンのクリックなどのユーザー操作の後に document.requestStorageAccess() 呼び出しを開始する必要があります。

例:

navigator.permissions.query({name: 'storage-access'}).then(res => {
  if (res.state === 'granted') {
    // Permission has already been granted
    // You can request storage access without any user gesture
    rSA();
  } else if (res.state === 'prompt') {
    // Requesting storage access requires user gesture
    // For example, clicking a button
    const btn = document.createElement("button");
    btn.textContent = "Grant access";
    btn.addEventListener('click', () => {
      // Request storage access
      rSA();
    });
    document.body.appendChild(btn);
  }
});

function rSA() {
  if ('requestStorageAccess' in document) {
    document.requestStorageAccess().then(
      (res) => {
        // Use storage access
      },
      (err) => {
        // Handle errors
      }
    );
  }
}

フレーム内、ナビゲーション内、またはサブリソースからの後続のリクエストには、クロスサイト Cookie へのアクセス権限が自動的に付与されます。hasStorageAccess() は true を返し、同じ関連ウェブサイト セットからのクロスサイト Cookie が追加の JavaScript 呼び出しなしでこれらのリクエストに送信されます。

埋め込み内ではなくトップレベル サイトで使用される requestStorageAccessFor() を示す図
別のオリジンのトップレベル サイトで requestStorageAccessFor() を使用する

トップレベル サイトは、特定の送信元の代わりに requestStorageAccessFor() を使用してストレージ アクセスをリクエストできます。

hasStorageAccess() は、呼び出し元のサイトにストレージへのアクセス権があるかどうかのみを確認するため、トップレベルのサイトは別のオリジンの権限を確認できます。

ユーザーにプロンプトが表示されるかどうか、または指定したオリジンにストレージ アクセスがすでに付与されているかどうかを調べるには、navigator.permissions.query({name: 'top-level-storage-access', requestedOrigin: 'https://target.site'}) を呼び出します。

権限が granted の場合は、document.requestStorageAccessFor('https://target.site') を呼び出すことができます。これは、ユーザー操作なしで成功するはずです。

権限が prompt の場合は、ボタンのクリックなどのユーザー操作の背後で document.requestStorageAccessFor('https://target.site') 呼び出しをフックする必要があります。

例:

navigator.permissions.query({name:'top-level-storage-access',requestedOrigin: 'https://target.site'}).then(res => {
  if (res.state === 'granted') {
    // Permission has already been granted
    // You can request storage access without any user gesture
    rSAFor();
  } else if (res.state === 'prompt') {
    // Requesting storage access requires user gesture
    // For example, clicking a button
    const btn = document.createElement("button");
    btn.textContent = "Grant access";
    btn.addEventListener('click', () => {
      // Request storage access
      rSAFor();
    });
    document.body.appendChild(btn);
  }
});

function rSAFor() {
  if ('requestStorageAccessFor' in document) {
    document.requestStorageAccessFor().then(
      (res) => {
        // Use storage access
      },
      (err) => {
        // Handle errors
      }
    );
  }
}

requestStorageAccessFor() 呼び出しが成功した後、クロスサイト リクエストに CORS または Crossorigin 属性が含まれている場合は Cookie が含まれるため、サイトはリクエストをトリガーする前に待機したい場合があります。

リクエストでは credentials: 'include' オプションを使用し、リソースには crossorigin="use-credentials" 属性を含める必要があります。

function checkCookie() {
    fetch('https://related-website-sets.glitch.me/getcookies.json', {
        method: 'GET',
        credentials: 'include'
      })
      .then((response) => response.json())
      .then((json) => {
      // Do something
      });
  }

ローカルでのテスト方法

前提条件

関連ウェブサイト セットをローカルでテストするには、コマンドラインから起動した Chrome 119 以降を使用して、test-third-party-cookie-phaseout Chrome フラグを有効にします。

Chrome フラグを有効にする

必要な Chrome フラグを有効にするには、アドレスバーから chrome://flags#test-third-party-cookie-phaseout に移動し、フラグを Enabled に変更します。フラグを変更したら、必ずブラウザを再起動してください。

ローカルで宣言された関連ウェブサイト セットを使用して Chrome を起動するには、セットのメンバーである URL を含む JSON オブジェクトを作成し、--use-related-website-set に渡します。

詳しくは、フラグを指定して Chromium を実行するをご覧ください。

--use-related-website-set="{\"primary\": \"https://related-website-sets.glitch.me\", \"associatedSites\": [\"https://rws-member-1.glitch.me\"]}" \
https://related-website-sets.glitch.me/

関連ウェブサイト セットをローカルで有効にするには、chrome://flagstest-third-party-cookie-phaseout を有効にし、--use-related-website-set フラグとセットのメンバーである URL を含む JSON オブジェクトを指定してコマンドラインから Chrome を起動する必要があります。

--use-related-website-set="{\"primary\": \"https://related-website-sets.glitch.me\", \"associatedSites\": [\"https://rws-member-1.glitch.me\"]}" \
https://related-website-sets.glitch.me/

クロスサイト Cookie にアクセスできることを確認する

テスト中のサイトから API(rSA または rSAFor)を呼び出し、クロスサイト Cookie へのアクセスを検証します。

ドメイン間の関係を宣言し、ドメインが属するサブセットを指定するには、次の手順を行います。

  1. 関連ドメインを特定します。これには、関連ウェブサイト セットの一部となる、プライマリ セットとメンバーが含まれます。また、各セットメンバーが属するサブセット タイプを特定します。
  2. 構成要件を設定し、検証要件を設定していることを確認します。
  3. 関連ウェブサイト セットを正しい JSON 形式で宣言します。
  4. Chrome が正規の関連ウェブサイト セットリストをホストする related_website_sets.JSONプル リクエスト(PR)を作成して、関連ウェブサイト セットを送信します。(PR を作成するには GitHub アカウントが必要です。また、このリストに投稿するには、コントリビューター ライセンス契約(CLA)に署名する必要があります)。

PR が作成されると、ステップ 2 の要件が満たされていることを検証するための一連のチェックが行われます。

成功すると、PR はチェックに合格したことを示します。承認された PR は、週に 1 回(火曜日午後 12 時(東部時間)に)、正規の関連ウェブサイト セット リストに一括して手動で統合されます。

いずれかのチェックが失敗した場合は、GitHub の PR エラーによって報告者に通知されます。報告者はエラーを修正し、PR を更新できます。次の点に注意してください。

  • PR が失敗した場合は、送信に失敗した理由に関する追加情報がエラー メッセージに表示されます()。
  • セットの送信を管理するすべてのテクニカル チェックは GitHub で実施されるため、技術的なチェックに起因する送信エラーはすべて GitHub で確認できます。

エンタープライズ ポリシー

企業ユーザーのニーズを満たすために、Chrome にはいくつかのエンタープライズ ポリシーがあります。

  • 関連ウェブサイト セットと統合できないシステムでは、RelatedWebsiteSetsEnabled ポリシーを使用して、Chrome のすべてのエンタープライズ インスタンスで関連ウェブサイト セット機能を無効にできます。
  • 一部の企業システムには、関連ウェブサイト セットのドメインとは異なる登録可能なドメインを持つ内部専用サイト(イントラネットなど)があります。ドメインは機密であるため、これらのサイトを一般公開せずに関連ウェブサイト セットの一部として扱う必要がある場合は、RelatedWebsiteSetsOverrides ポリシーを使用して、公開されている関連ウェブサイト セットのリストを拡張またはオーバーライドできます。

「ユーザー プロンプト」と「ユーザー操作」

「ユーザー プロンプト」と「ユーザー操作」は別物です。同じ関連ウェブサイト セット内のサイトの場合、ユーザーに権限のプロンプトは表示されませんが、ユーザーがページで操作していることは引き続き必要です。Chrome では、権限を付与する前にユーザー操作(「ユーザー操作」または「ユーザー アクティベーション」とも呼ばれます)が必要です。これは、ウェブ プラットフォームの設計原則により、関連ウェブサイト セットのコンテキスト(requestStorageAccess())の外部で Storage Access API を使用する場合もユーザー操作が必要になるためです。

他のサイトの Cookie やストレージにアクセスする

関連ウェブサイト セットでは、異なるサイトのストレージは統合されません。requestStorageAccess() を簡単に(プロンプトなしで)呼び出すことができます。関連ウェブサイト セットは、Storage Access API を使用するユーザーの負担を軽減するのみで、アクセス権の復元後に何をすべきかを指定するものではありません。A と B が同じ関連ウェブサイト セット内の異なるサイトで、A が B を埋め込んでいる場合、B は requestStorageAccess() を呼び出して、ユーザーにプロンプトを表示せずにファースト パーティ ストレージにアクセスできます。関連ウェブサイト セットはクロスサイト通信を行いません。たとえば、関連ウェブサイト セットを設定しても、B に属する Cookie が A に送信されるようになることはありません。そのデータを共有する場合は、B iframe から A フレームに window.postMessage を送信するなどして、自分でデータを共有する必要があります。

関連ウェブサイト セットでは、API を呼び出すことなく、パーティション分割されていない Cookie への暗黙的なアクセスは許可されません。このセット内のデフォルトでは、クロスサイト Cookie は使用できません。関連ウェブサイト セットは、セット内のサイトが Storage Access API 権限プロンプトをスキップすることのみを許可します。iframe が Cookie にアクセスするには document.requestStorageAccess() を呼び出す必要があります。また、トップレベルのページで document.requestStorageAccessFor() を呼び出すこともできます。

フィードバックを共有

GitHub にセットを送信し、Storage Access API と requestStorageAccessFor API を使用して、プロセスや問題に関する経験を共有する機会となります。

関連ウェブサイト セットに関するディスカッションに参加するには: