Storage Access API

ブラウザ、ユーザー設定、ストレージ パーティショニングによるサードパーティ Cookie のブロックは、埋め込みコンテキストで Cookie やその他のストレージを使用するサイトやサービスで、認証などのユーザー ジャーニーにおいて課題となります。Storage Access API(SAA)を使用すると、クロスサイト トラッキングを可能な限り制限しながら、これらのユースケースを引き続き機能させることができます。

実装ステータス

対応ブラウザ

  • Chrome: 119。 <ph type="x-smartling-placeholder">
  • Edge: 85。
  • Firefox: 65。 <ph type="x-smartling-placeholder">
  • Safari: 11.1。 <ph type="x-smartling-placeholder">

ソース

Storage Access API はすべての主要なブラウザで使用できますが、ブラウザによって実装に若干の違いがあります。これらの違いについては、この投稿の関連セクションで取り上げています。

API の標準化の前に、残っている問題をすべて解決する取り組みが継続されています。

Storage Access API とは

Storage Access API は、ブラウザの設定でアクセスが拒否される場合に、iframe がストレージへのアクセス権限をリクエストできるようにする JavaScript API です。クロスサイト リソースの読み込みに依存するユースケースの埋め込みでは、API を使用して、必要に応じてユーザーにアクセス権限をリクエストできます。

ストレージ リクエストが承認されると、iframe はパーティション化されていない Cookie とストレージにアクセスできるようになります。これは、ユーザーがトップレベル サイトとしてアクセスした場合にも利用できます。

Storage Access API を使用すると、エンドユーザーの負担を最小限に抑えながら、特定のパーティション分割されていない Cookie とストレージへのアクセスを提供できます。その一方で、ユーザーのトラッキングでよく使われるようなパーティション分割されていない一般的な Cookie やストレージへのアクセスは防止できます。

ユースケース

一部のサードパーティ埋め込みでは、ユーザー エクスペリエンスを向上させるために、パーティション分割されていない Cookie またはストレージへのアクセスが必要となります。これは、サードパーティ Cookie が制限され、ストレージ パーティショニングが有効になっている場合は利用できなくなります。

ユースケースの例:

  • ログイン セッションの詳細情報を必要とする埋め込みコメント ウィジェット。
  • ソーシャル メディアの「高評価」ログイン セッションの詳細情報を要求するボタン
  • ログイン セッションの詳細情報を必要とする埋め込みドキュメント。
  • 埋め込み動画の高度な機能(たとえば、ログイン ユーザーには広告を表示しない、字幕に関するユーザー設定を把握する、特定の動画タイプを制限するなど)。
  • 組み込みの支払いシステム。

これらのユースケースの多くには、埋め込み iframe でログイン アクセスを持続させることが含まれます。

他の API ではなく Storage Access API を使用する場合

Storage Access API は、パーティション分割されていない Cookie とストレージを使用する代替手段の 1 つであるため、この API を使用するタイミングを他の API と比較して理解することが重要です。次の両方に該当するユースケースを対象としています。

  • ユーザーは埋め込みコンテンツを操作します。つまり、パッシブ iframe や隠し iframe ではありません。
  • ユーザーがトップレベル コンテキストで埋め込まれたオリジンにアクセスした(そのオリジンが別のサイトに埋め込まれていないとき)。

さまざまなユースケースに対応する代替 API が用意されています。

  • Cookies Having Independent Partitioned State(CHIPS)により、デベロッパーは Cookie を「パーティション分割」にオプトインできます。Cookie ビンをトップレベル サイトごとに分けて作成します。たとえば、サードパーティのウェブチャット ウィジェットは、セッション情報を保存するために Cookie の設定に依存することがあります。セッション情報はサイトごとに保存されるため、ウィジェットで設定された Cookie が埋め込まれている他のウェブサイトからアクセスする必要はありません。Storage Access API は、埋め込まれたサードパーティ製ウィジェットが、異なるオリジンで同じ情報(ログイン セッションの詳細や設定など)を共有することに依存している場合に役立ちます。
  • ストレージ パーティショニングは、クロスサイト iframe が既存の JavaScript ストレージ メカニズムを使用し、基盤となるストレージをサイトごとに分割する方法です。これにより、あるウェブサイトの埋め込みストレージが、他のウェブサイトにある同じ埋め込みストレージからアクセスされるのを防ぐことができます。
  • 関連ウェブサイト セット(RWS)は、組織がサイト間の関係を宣言して、ブラウザが制限されているパーティショニングされていない Cookie とストレージへの特定の目的でのアクセスを許可できるようにする方法です。サイトは引き続き Storage Access API でアクセスをリクエストする必要がありますが、このセット内のサイトについては、ユーザーにプロンプトを表示せずにアクセスを許可できます。
  • Federated Credential Management(FedCM)は、ID 連携サービスに対するプライバシー保護アプローチです。Storage Access API は、パーティション分割されていない Cookie へのアクセスとログイン後のストレージを処理します。ユースケースによっては、Storage Access API に代わるソリューションとして FedCM が提供されています。FedCM はログイン指向のブラウザ プロンプトを備えているため、望ましい場合があります。ただし、FedCM を採用するには通常、HTTP エンドポイントのサポートなど、コードの追加変更が必要になります。
  • 不正防止 API、広告関連 API測定 API もありますが、Storage Access API はこれらの懸念に対処することを意図したものではありません。

Storage Access API を使用する

Storage Access API には、Promise ベースのメソッドが 2 つあります。

Permissions API とも統合されています。これにより、サードパーティのコンテキストでストレージ アクセス権限のステータスを確認できます。これは、document.requestStorageAccess() への呼び出しが自動的に許可されるかどうかを示します。

hasStorageAccess() メソッドを使用する

サイトが最初に読み込まれるときに、hasStorageAccess() メソッドを使用して、サードパーティ Cookie へのアクセスがすでに付与されているかどうかを確認できます。

// Set a hasAccess boolean variable which defaults to false.
let hasAccess = false;

async function handleCookieAccessInit() {
  if (!document.hasStorageAccess) {
    // Storage Access API is not supported so best we can do is
    // hope it's an older browser that doesn't block 3P cookies.
    hasAccess = true;
  } else {
    // Check whether access has been granted using the Storage Access API.
    // Note on page load this will always be false initially so we could be
    // skipped in this example, but including for completeness for when this
    // is not so obvious.
    hasAccess = await document.hasStorageAccess();
    if (!hasAccess) {
      // Handle the lack of access (covered later)
    }
  }
  if (hasAccess) {
    // Use the cookies.
  }
}
handleCookieAccessInit();

iframe ドキュメントへのストレージ アクセスは、requestStorageAccess(), が呼び出された後にのみ付与されるため、hasStorageAccess() は最初に常に false を返します。ただし、同じ iframe 内の別の同一生成元のドキュメントにすでにアクセス権が付与されている場合を除きます。この付与は iframe 内の同一オリジン ナビゲーション全体で保持されます。これは、HTML ドキュメントに対する最初のリクエストに Cookie の存在が必要なページへのアクセスを許可した後の再読み込みを可能にするためです。

requestStorageAccess()

iframe にアクセス権がない場合は、requestStorageAccess() メソッドを使用してアクセス権をリクエストする必要があります。

if (!hasAccess) {
  try {
    await document.requestStorageAccess();
  } catch (err) {
    // Access was not granted and it may be gated behind an interaction
    return;
  }
}

これが初めてリクエストされたときに、ユーザーはブラウザ プロンプトでこのアクセスを承認する必要がある場合があります。その後 Promise が解決されるか、await が使用されている場合は拒否されて例外が発生します。

不正行為を防止するため、このブラウザのプロンプトはユーザーの操作後にのみ表示されます。そのため、requestStorageAccess() は、iframe の読み込み直後ではなく、ユーザーがアクティブにしたイベント ハンドラから最初に呼び出す必要があります。

async function doClick() {

  // Only do this extra check if access hasn't already been given
  // based on the hasAccess variable.
  if (!hasAccess) {
    try {
      await document.requestStorageAccess();
      hasAccess = true; // Can assume this was true if requestStorageAccess() did not reject.
    } catch (err) {
      // Access was not granted.
      return;
    }
  }

  if (hasAccess) {
    // Use the cookies
  }
}

document.querySelector('#my-button').addEventListener('click', doClick);
<ph type="x-smartling-placeholder">

Cookie の代わりにローカル ストレージを使用する必要がある場合は、次のようにします。

let handle = null;

async function doClick() {
  if (!handle) {
    try {
      handle = await document.requestStorageAccess({localStorage: true});
    } catch (err) {
      // Access was not granted.
      return;
    }
  }

  // Use handle to access unpartitioned local storage.
  handle.localStorage.setItem('foo', 'bar');
}

document.querySelector('#my-button').addEventListener('click', doClick);

権限プロンプト

ユーザーが初めてボタンをクリックしたときに、ブラウザ プロンプトで 通常はアドレスバーに表示されます。次のスクリーンショット に Chrome のプロンプトの例を示します。ただし、他のブラウザでも同様の UI があります。

Chrome Storage Access API の権限プロンプト
Chrome の Storage Access API の権限プロンプト

次のような特定の状況では、ブラウザでプロンプトがスキップされ、権限が自動的に提供されることがあります。

  • プロンプトの承認後、過去 30 日間にページと iframe が使用されているかどうか。
  • 埋め込み iframe が関連ウェブサイト セットの一部である場合。
  • Firefox では、既知のウェブサイト(最上位レベルで操作したウェブサイト)でも、最初の 5 回の試行ではプロンプトがスキップされます。

また、特定の状況では、プロンプトを表示せずにメソッドが自動的に拒否される場合があります。

  • iframe 内ではなく、トップレベルのドキュメントとして iframe を所有しているサイトにユーザーがアクセスしたことがなく、操作したことがない場合。つまり、Storage Access API は、ユーザーが以前にファーストパーティのコンテキストでアクセスした埋め込みサイトにのみ有用です。
  • 操作後のプロンプトに対する事前の承認なしに、ユーザー操作イベントの外部で requestStorageAccess() メソッドが呼び出された場合。

初回の使用時にはメッセージが表示されますが、2 回目以降のアクセスでは、Chrome や Firefox でユーザーが操作しなくても requestStorageAccess() を解決できます。Safari では常にユーザーの操作が必要です。

Cookie とストレージへのアクセス権は、プロンプトやユーザーの操作なしで付与される場合があるため、多くの場合、ページ読み込み時に requestStorageAccess() を呼び出すことで、この機能をサポートしているブラウザ(Chrome と Firefox)でユーザーが操作を行う前に、パーティション分割されていない Cookie またはストレージへのアクセス権を取得できます。これにより、ユーザーが iframe を操作する前でも、パーティション分割されていない Cookie やストレージにすぐにアクセスして、完全なエクスペリエンスを提供できます。これにより、状況によっては、ユーザーの操作を待つよりもユーザー エクスペリエンスが向上することがあります。

storage-access 権限クエリを使用する

ユーザーの操作なしでアクセス権が付与されるかどうかを確認するには、storage-access 権限のステータスを確認し、ユーザーの操作が必要な場合にのみ requestStoreAccess() 呼び出しを早期に行います。操作の必要な場合に呼び出して失敗するようにします。

また、さまざまなコンテンツ(ログインボタンなど)を表示することで、事前のプロンプトの必要性に対処することもできます。

次のコードは、前の例に storage-access 権限チェックを追加したものです。

// Set a hasAccess boolean variable which defaults to false except for
// browsers which don't support the API - where we assume
// such browsers also don't block third-party cookies.
let hasAccess = false;

async function hasCookieAccess() {
  // Check if Storage Access API is supported
  if (!document.requestStorageAccess) {
    // Storage Access API is not supported so best we can do is
    // hope it's an older browser that doesn't block 3P cookies.
    return true;
  }

  // Check if access has already been granted
  if (await document.hasStorageAccess()) {
    return true;
  }

  // Check the storage-access permission
  // Wrap this in a try/catch for browsers that support the
  // Storage Access API but not this permission check
  // (e.g. Safari and earlier versions of Firefox).
  let permission;
  try {
    permission = await navigator.permissions.query(
      {name: 'storage-access'}
    );
  } catch (error) {
    // storage-access permission not supported. Assume no cookie access.
    return false;
  }

    if (permission) {
    if (permission.state === 'granted') {
      // Permission has previously been granted so can just call
      // requestStorageAccess() without a user interaction and
      // it will resolve automatically.
      try {
        await document.requestStorageAccess();
        return true;
      } catch (error) {
        // This shouldn't really fail if access is granted, but return false
        // if it does.
        return false;
      }
    } else if (permission.state === 'prompt') {
      // Need to call requestStorageAccess() after a user interaction
      // (potentially with a prompt). Can't do anything further here,
      // so handle this in the click handler.
      return false;
          } else if (permission.state === 'denied') {
            // Not used: see https://github.com/privacycg/storage-access/issues/149
      return false;
          }
    }

  // By default return false, though should really be caught by earlier tests.
  return false;
}

async function handleCookieAccessInit() {
  hasAccess = await hasCookieAccess();

  if (hasAccess) {
    // Use the cookies.
  }
}

handleCookieAccessInit();
<ph type="x-smartling-placeholder">

サンドボックス化された iframe

サンドボックス化された iframe で Storage Access API を使用する場合は、次のサンドボックスの権限が必要です。

  • allow-storage-access-by-user-activation は、Storage Access API へのアクセスを許可するために必要です。
  • JavaScript を使用して API を呼び出すには、allow-scripts が必要です。
  • 同一生成元の Cookie やその他のストレージへのアクセスを許可するには、allow-same-origin が必要です。

例:

<iframe sandbox="allow-storage-access-by-user-activation
                 allow-scripts
                 allow-same-origin"
        src="..."></iframe>

Chrome で Storage Access API を使用してアクセスするには、次の 2 つの属性でクロスサイト Cookie を設定する必要があります。

  • SameSite=None - Cookie をクロスサイトとしてマークするために必要です。
  • Secure - HTTPS サイトによって設定された Cookie にのみアクセスできます。

Firefox と Safari では、Cookie はデフォルトで SameSite=None に設定され、SAA を Secure Cookie に制限しないため、これらの属性は必要ありません。SameSite 属性を明示的に指定し、常に Secure Cookie を使用することをおすすめします。

トップレベルのページへのアクセス

Storage Access API は、埋め込み iframe 内でサードパーティ Cookie にアクセスできるようにするためのものです。

他にも、トップレベル ページでサードパーティ Cookie へのアクセスが必要なユースケースがあります。たとえば、Cookie によって制限されている画像やスクリプトを iframe ではなく最上位のドキュメントに直接含めたいサイト所有者がいるとします。このユースケースに対応するため、Chrome では requestStorageAccessFor() メソッドを追加する Storage Access API の拡張を提案しています。

requestStorageAccessFor() メソッド

対応ブラウザ

  • Chrome: 119。 <ph type="x-smartling-placeholder">
  • Edge: 119。 <ph type="x-smartling-placeholder">
  • Firefox: サポートされていません。 <ph type="x-smartling-placeholder">
  • Safari: サポートされていません。 <ph type="x-smartling-placeholder">

ソース

requestStorageAccessFor() メソッドは requestStorageAccess() と同じように動作しますが、最上位のリソースを対象とします。サードパーティ Cookie への一般的なアクセス権の付与を防ぐために、関連ウェブサイト セット内のサイトでのみ使用できます。

requestStorageAccessFor() の使用方法について詳しくは、関連ウェブサイト セット: デベロッパー ガイドをご覧ください。

top-level-storage-access 権限クエリ

対応ブラウザ

  • Chrome: サポートされていません。
  • Edge: サポートされていません。 <ph type="x-smartling-placeholder">
  • Firefox: サポートされていません。 <ph type="x-smartling-placeholder">
  • Safari: サポートされていません。 <ph type="x-smartling-placeholder">

storage-access 権限と同様に、requestStorageAccessFor() にアクセス権を付与できるかどうかを確認する top-level-storage-access 権限があります。

RWS で使用する場合の Storage Access API の違い

関連ウェブサイト セットを Storage Access API で使用する場合、次の表で示すような追加機能を利用できます。

RWS なし RWS 搭載
ストレージへのアクセス リクエストを開始するにはユーザー操作が必要
アクセス権を付与する前に、最上位のコンテキストでリクエストされたストレージ オリジンにアクセスする必要がある
初回ユーザー メッセージはスキップ可能
requestStorageAccess: アクセスがすでに付与されている場合は呼び出す必要はありません
関連ウェブサイト サイトの他のドメインのアクセス権を自動的に付与します
最上位レベルのページへのアクセスをrequestStorageAccessFor サポートします
Storage Access API を使用する場合、関連ウェブサイト セットを使用する場合と使用しない場合の違い

デモ: Cookie の設定とアクセス

次のデモは、デモの最初の画面で設定した Cookie に、デモの 2 番目のサイトの埋め込みフレームでアクセスする方法を示しています。

storage-access-api-demo.glitch.me

このデモでは、サードパーティ Cookie が無効になっているブラウザが必要です。

  • chrome://flags/#test-third-party-cookie-phaseout フラグを設定し、ブラウザを再起動した Chrome 118 以降。
  • Firefox
  • Safari

デモ: ローカル ストレージの設定

次のデモは、Storage Access API を使用して、サードパーティの iframe からパーティショニングされていないブロードキャスト チャネルにアクセスする方法を示しています。

https://saa-beyond-cookies.glitch.me/

このデモを行うには、test-third-party-cookie-phaseout フラグを有効にした Chrome 125 以降が必要です。

リソース