Storage Access API

Chrome では、クロスサイト トラッキングを減らすために、サードパーティ Cookie のサポートを段階的に廃止し、ストレージのパーティショニングを行っています。このことは、認証などのユーザー ジャーニーにおいて、埋め込みコンテキストで Cookie やその他のストレージに依存するサイトやサービスにとって課題となります。Storage Access API(SAA)を使用すると、こうしたユースケースを引き続き使用しながら、クロスサイト トラッキングを可能な限り制限できます。

実装ステータス

対応ブラウザ

  • 119
  • 85
  • 65
  • 11.1

ソース

Storage Access API はすべての主要なブラウザで使用できますが、ブラウザごとに実装が若干異なります。これらの違いは、この投稿の関連セクションで強調されています。

API の標準化の前に、残っているすべてのブロックの問題が引き続き解決されています。

Storage Access API とは何ですか?

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

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

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

ユースケース

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

次のようなユースケースがあります。

  • ログイン セッションの詳細を必要とする埋め込みコメント ウィジェット。
  • ログイン セッションの詳細情報を要求するソーシャル メディアの「いいね」ボタン。
  • ログイン セッションの詳細を必要とする埋め込みドキュメント。
  • 動画の埋め込みに提供される特別な機能(ログイン ユーザーに対して広告を表示しないようにする、字幕のユーザー設定を確認する、特定の動画タイプを制限するなど)。
  • 埋め込み決済システム。

このようなユースケースの多くは、埋め込み iframe でのログイン アクセスの永続化に関係しています。

他の API よりも Storage Access API を使用する場合

Storage Access API は、パーティション分割されていない Cookie とストレージの代替手段の一つです。そのため、この API と他の API の用途の違いを理解することが重要です。次の条件が両方とも満たされているユースケース向けです。

  • 埋め込みコンテンツは、ユーザーが操作します。つまり、パッシブな iframe や非表示の iframe ではありません。
  • ユーザーが最上位のコンテキストで埋め込みオリジンにアクセスしました。つまり、そのオリジンが別のサイトに埋め込まれていない場合です。

さまざまなユースケースに対応する代替 API があります。

  • Cookie の Independent Partitioned State(CHIPS)を使用すると、デベロッパーはトップレベル サイトごとに別個の Cookie jar を持つ「パーティション分割」ストレージに Cookie をオプトインできます。たとえば、サードパーティのウェブチャット ウィジェットは、セッション情報を保存するために Cookie の設定に依存することがあります。セッション情報はサイトごとに保存されるため、ウィジェットが設定した Cookie が埋め込まれている他のウェブサイトからアクセスする必要はありません。Storage Access API は、埋め込まれたサードパーティ ウィジェットが、異なる生成元間で同じ情報(ログイン中のセッションの詳細や設定など)の共有に依存している場合に役立ちます。
  • ストレージ パーティショニングは、クロスサイト iframe が既存の JavaScript ストレージ メカニズムを使用し、基盤となるストレージをサイトごとに分割する方法です。これにより、あるウェブサイトの埋め込みストレージが、他のウェブサイトの同じ埋め込みによってアクセスされるのを防ぐことができます。
  • 関連ウェブサイト セット(RWS)は、組織がサイト間の関係を宣言するための方法です。ブラウザは特定の目的のために、パーティション分割されていない Cookie とストレージへのアクセスを限定的に許可します。サイトは引き続き Storage Access API を使用してアクセス権をリクエストする必要がありますが、セット内のサイトについては、ユーザーにプロンプトを表示せずにアクセスを許可できます。
  • Federated Credential Management(FedCM)は、フェデレーション ID サービスに関するプライバシー保護アプローチです。Storage Access API は、パーティション分割されていない Cookie とログイン後のストレージへのアクセスを処理します。一部のユースケースでは、FedCM は Storage Access API の代替ソリューションを提供します。よりログイン指向のブラウザ プロンプトが特徴であるため、FedCM が好ましい場合があります。ただし、FedCM を導入するには、通常、HTTP エンドポイントをサポートするなど、コードに追加の変更が必要になります。
  • 不正行為広告関連測定の 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 via 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 above did not reject.
    } catch (err) {
      // Access was not granted.
      return;
    }
  }

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

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

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 権限プロンプト

次のような状況では、ブラウザによってプロンプトがスキップされ、権限が自動的に付与されます。

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

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

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

初回使用時にユーザーにプロンプトが表示されますが、それ以降のアクセスは 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 older 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') {
            // Currently not used. See:
      // https://github.com/privacycg/storage-access/issues/149
      return false;
          }
    }

  // By default return false, though should really be caught by one of above.
  return false;
}

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

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

handleCookieAccessInit();

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

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

  • Storage Access API へのアクセスを許可するには、allow-storage-access-by-user-activation が必要です。
  • 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 に設定され、SSA は Secure Cookie に制限されないため、これらの属性は必要ありません。SameSite 属性を明示的に指定し、常に Secure Cookie を使用することをおすすめします。

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

Storage Access API は、埋め込み iframe 内でサードパーティの Cookie にアクセスできるようにすることを目的としています。

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

requestStorageAccessFor() メソッド

対応ブラウザ

  • 119
  • 119
  • x
  • x

ソース

requestStorageAccessFor() メソッドは requestStorageAccess() と同様に機能しますが、トップレベルのリソースを対象にします。サードパーティ Cookie への一般的なアクセスを許可できないようにするために、関連ウェブサイト セット内のサイトにのみ使用できます。

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

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

対応ブラウザ

  • x
  • x
  • x
  • x

storage-access 権限と同様に、requestStorageAccessFor() にアクセスを許可できるかどうかをチェックする top-level-storage-access 権限があります。

Storage Access API を RWS で使用する場合、どのような違いがありますか?

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/

このデモでは、Chrome 125 以降で test-third-party-cookie-phaseout フラグを有効にする必要があります。

リソース