First-Party Setsでドメインを超えてCookieを共有する

以下はGoogleが勧めている[プライバシーサンドボックス](https://web.dev/digging-into-the-privacy-sandbox/)技術のひとつ、[First-Party Sets](https://github.com/privacycg/first-party-sets)の紹介です。
細かい部分とかはよくわからないので端折ってたり想像で補ったりしている場合があります。
きっと誰かが正確な訳をプルリクしてくれるはず。

# First-Party Sets

本文書は、関連するドメインをまとめてひとつのファーストパーティであると宣言するための、新しいWebプラットフォームメカニズムの提案です。

## Introduction

ブラウザは様々なトラッキングポリシーやプライバシーモデルを提案しており( [Chromium](https://github.com/michaelkleber/privacy-model/blob/master/README.md) / [Edge](https://blogs.windows.com/msedgedev/2019/06/27/tracking-prevention-microsoft-edge-preview/) / [Mozilla](https://wiki.mozilla.org/Security/Anti_tracking_policy) / [WebKit](https://webkit.org/tracking-prevention-policy/) )、個人情報にアクセスできる範囲をファーストパーティに限定しています。
ファーストパーティの範囲を定義する際には、2つの目標のバランスをとる必要があります。
すなわち、ユーザのプライバシーを守るのに十分な小さな範囲であり、かつユーザが望む機能を提供するのに十分な大きさであることです。

ファーストパーティの自然な範囲としては、ドメイン名があります。
しかし、ユーザのアクセスするWebサイトが複数のドメインにまたがっている場合もあります。
たとえば`https://google.com`と`https://google.co.uk`と`https://youtube.com`はひとつの組織によって運営されています。
あるいは`https://apple.com`と`https://icloud.com`、`https://amazon.com`と`https://amazon.de`なども同様です。

プライバシー要求と矛盾しない範囲で、ユーザ情報を関連するオリジンに共有することを許可したい場合があります。
たとえばFirefoxには、同じ組織に属するドメインのリストが同梱されています。
このドキュメントでは、組織がそれぞれ独自のドメインリストを宣言し、そのセットがブラウザのポリシーに適合する場合にブラウザがそれを取り入れることを許可するメカニズムについて解説します。

## Goals

・関連するドメインが同じファーストパーティであることを宣言できるようにする。
・宣言されたドメインを同じサイトとして扱うか否か、プライバシーポリシーの枠組みを定義する。

## Non-goals

・無関係なサイト間でのサードパーティーログイン。
・ターゲティング広告やコンバージョン測定のための無関係なサイト間での情報共有。

これらのユースケースの一部については、プライバシーポリシーの[他の領域](https://www.chromium.org/Home/chromium-privacy/privacy-sandbox)でサポートされています。

## Declaring a First Party Set

First-Party Setsは、ひとつのオーナードメインと、二次登録ドメインのリストによって構成されます。

以下の条件を満たすオリジンは、ファーストパーティセットを構成します。

・httpsである。
・登録ドメインがオーナーであるか、二次登録ドメインのひとつである。

ドメインがオプトインされていて、[UAポリシー](#ua-policy)が[ユーザとサイトのニーズ](https://www.w3.org/TR/html-design-principles/#priority-of-constituencies)に適合する場合、ブラウザはそのドメインをファーストパーティセットのメンバーであるとみなします。

ファーストパーティセットに参加するには、JSONのマニフェストファイル`https://<domain>/.well-known/first-party-set`を設置します。
二次登録ドメインではオーナードメインを指定し、オーナードメインでは所有する二次登録ドメイン、バージョン番号、UAポリシーの署名の一覧を記述します。

例として、`a.example`・`b.example`・`c.example`がファーストパーティセットであり、オーナードメインが`a.example`である場合は、以下のようになります。

```json
https://a.example/.well-known/first-party-set
{
  "owner": "a.example",
  "version": 1,
  "members": ["b.example", "c.example"],
  "assertions": { 
    "chrome-fps-v1" : "<base64 contents...>",
    "firefox-fps-v1" : "<base64 contents...>",
    "safari-fps-v1": "<base64 contents...>"
  }
}

https://b.example/.well-known/first-party-set
{ "owner": "a.example" }

https://c.example/.well-known/first-party-set
{ "owner": "a.example" }
```

ブラウザはオーナードメインのマニフェストに以下の制約を追加します。

・`members`記載の登録可能ドメインのうち、登録可能でない場合は無視する。
・`members`記載の二次登録ドメインのうち、[UAポリシー](#ua-policy)に合致する場合のみ受け入れる。合致しない二次登録ドメインは無視する。
・オーナードメイン自体がUAポリシーに合致しない場合、全てが無視される。

## Discovering First Party Sets

デフォルトでは、全ての登録可能なドメインは、自分自身がオーナードメインです。
Webサイトは`Sec-First-Party-Set`レスポンスヘッダを送信し、ファーストパーティセットのオーナードメインをブラウザに知らせることができます。
たとえば、`https://b.example/some/page`は以下のようなレスポンスヘッダを出力することができます。

```text
  Sec-First-Party-Set: owner="a.example", minVersion=1
```

ブラウザが所有している`b.example`の情報がこのヘッダと一致しない場合、ブラウザはナビゲーションを一時停止して2ドメインのマニフェスト、すなわち`https://a.example/.well-known/first-party-set`と`https://b.example/.well-known/first-party-set`を取得します。
このリクエストは認証情報を用いず、またクロスサイトでリクエストしているという情報を漏洩しないように注意しなければなりません。
特に`a.example`においてはキャッシュを使ってはいけません。

マニフェストファイルの両方にドメインが含まれていることを確認したら、ブラウザは`a.example`を`b.example`のオーナーとしてファーストパーティストレージに登録します。
`c.example`は入りません。
またこのときに、`a.example`がオーナーであるとファーストパーティストレージに記録されているドメインのうち、新しいマニフェストファイルからなくなったものを削除します。

次に、オーナーが変更されたドメインについて、`Clear-Site-Data`と同じ動作で全てのキャッシュを削除し、アクティブなドキュメントを再読み込みします。
これはオーナーから外れたサイトへの関連付けを解除するために必要な動作です。
オーナーが変更になった際に、既存の実行コンテキスト(worker等)は破棄されます。

その後、ブラウザはリクエストを再試行し、ナビゲーションを完了します。
POSTの再試行は望ましくないため、POSTリクエストにおいてブラウザは`Sec-First-Party-Set`レスポンスヘッダは無視すべきです。
POSTでファーストパーティセットを更新したいサイトは、POST後にリダイレクトを行い、リダイレクト先で`Sec-First-Party-Set`レスポンスヘッダを返すようにします。

サブリソースやサブフレームのナビゲーションにおいては、新たなファーストパーティセットを登録することはできません。

## Applications

様々なブラウザのプライバシーモデルをサポートするために、Webプラットフォームはファーストパーティセットを通じて、埋め込みコンテンツが自身のステータスにアクセスしてもよいか決定することができます。
たとえばCookieの[SameParty属性](https://github.com/cfredric/sameparty)を利用して、クロスドメインで送信するCookieアノテートすることができます。また、厳格なオリジンベースの分離が高コストになる場合に、ファーストパーティセットを使用してネットワークキャッシュを分散することでコストを抑えられるかもしれません。

Webプラットフォームは、あるオリジンの中身に別のオリジンが直接アクセスすることを目的としてファーストパーティセットを使用するべきではありません。
ファーストパーティセットは、埋め込みコンテンツが自身の状態にアクセスする場合にのみ限定すべきです。
たとえば`a.example`と`b.example`がひとつのファーストパーティセットにあるとして、`a.example`のコンテンツが`b.example`のIndexedDBにアクセスすることはできないようにすべきです。
ただし、`a.example`内にフレームで表示されている`b.example`のコンテンツが、`b.example`のデータベースにアクセスすることは妥当かもしれません。

## Design details

### UA Policy

#### Defining acceptable sets

どのようなセットを許可するか、あるいは受け入れられないかについて、ある程度制限を持っておく必要があります。
たとえばWeb全体を含むセットや、全く関係ないサイトの集まりは明らかに受け入れられないと思われます。
逆に`https://acme-corp-landing-page.example`と`https://acme-corp-online-store.example`を含むセットは妥当だと思われます。
この両者の間には幅広いスペースがあり、どこで線を引くのかを定義しなければなりません。

ファーストパーティセットを実装するブラウザは、どのドメインがどのセットに含まれるかについてUAポリシーを定義します。
必須ではありませんが、UAポリシー間である程度の一貫性があることが望ましいでしょう。
UAポリシーを定義する際の指針としては、各ブラウザがファーストパーティをどのように考えているかを参考にすることができます。

##### [A Potential Privacy Model for the Web (Chromium Privacy Sandbox)](https://github.com/michaelkleber/privacy-model/blob/master/README.md)
ファーストパーティの概念は、`eTLD+1`を超えて拡張される可能性があります。
結果の範囲が広すぎず、ユーザの理解があることを前提に、ファーストパーティの制限を緩和することは合理的です。

##### [Edge Tracking Protection Preview](https://blogs.windows.com/msedgedev/2019/06/27/tracking-prevention-microsoft-edge-preview/)

全ての組織がひとつのドメイン名だけを使ってインターネットビジネスを展開しているわけではありません。
サイトの円滑な運用のため、ひとつの組織が所有・運営する複数のドメインをまとめています。

##### [Mozilla Anti-Tracking Policy](https://wiki.mozilla.org/Security/Anti_tracking_policy)

ファーストパーティとは、同一組織が運営するウェブ上のリソースもしくはリソース群のことで、ユーザが容易に発見でき、リンクをクリックしたリフォームを送信するなど相互作用を行うものです。

##### [WebKit Tracking Prevention Policy](https://webkit.org/tracking-prevention-policy/)

ファーストパーティとは、ブラウザのURLフィールドに表示される、ユーザが意図的かつ承認したうえで訪問しているWebサイト、および同じ組織が運営するウェブ上のリソースの集合です。


UAポリシーは、ユースケースや不正使用などの対策に応じて、時間をかけて進化していくものと考えています。
たとえば無関係なサイトがファーストパーティの範囲を広げるためにコンソーシアムを形成することは悪用とみなされます。

UAポリシーはユーザのブラウザに配信されなければなりません。
これは静的なリスト、もしくは署名されたアサーションのいずれかを使用できます。

ファーストパーティセットのメンバーになるには、UAポリシーを満たすことと、マニフェストファイルによる記載の両方が必要となります。
これによって、Webサイトはファーストパーティセットから無関係なドメインを迅速に排除できます。

#### Static lists

ブラウザベンダは、自社のUAポリシーを満たすドメインリストをそれぞれで管理し、ブラウザに搭載することができます。
これはEdgeやFirefoxがクロスサイトトラッキングを制御するために使っている[同一オーナーのドメインリスト](https://github.com/disconnectme/disconnect-tracking-protection/blob/master/entities.json)と同じようなものです。

このリストを使う場合は、ファーストパーティセットのマニフェストと合体して使います。

静的リストは制御や検査が簡単です。
その一方でスケーラビリティや即応性に問題が生じます。
リストの変更を、何らかのメカニズムで各ブラウザに送り付ける必要があります。
特にネットワーク接続性に困難のある地域では、新しいドメインリストを展開することが難しくなります。
またリストが大きくなりすぎるとスケーラビリティにも問題が起こります。

#### Signed assertions

ブラウザベンダー、およびベンダーが指定したオーナーは、秘密鍵を用いてドメインのアサーションに署名することができます。
署名されたアサーションは静的リストと同格の意味を持ちます。


#### Administrative controls

エンタープライズユースでは、Webプラットフォームの動作を制御するためにブラウザは管理者用オプションを提供します。
UPポリシーをプライベートドメインに適用するとは考えにくいので、ブラウザはローカル向けのファーストパーティセットを取り込むオプションを提供するかもしれません。

### Cross-site tracking vectors

この設計では、ブラウザがファーストパーティセットの状態を記憶し、その状態を使ってサイトの動作を管理する必要があります。
この状態を、ファーストパーティが異なる2つのサイトにクロスサイトで渡さないようにしなければなりません。
たとえば、あるサイトがユーザ識別子をファーストパーティセットに登録し、その識別子を別のサイトから読めるようにすることができるかもしれません。
また、ファーストパーティセットはオンデマンドで発見・検証されるため、どのサイトを訪問したかの情報が漏洩する可能性があります。

これらの攻撃への対策は、ファーストパーティセットはファーストパーティに限定することです。
現在のセット以外のファーストパーティセット情報を読み書きすることはできません。

また認証を使用せずにマニフェストを取得するため、検証時の漏洩も防ぐことができます。

最後に、ユーザがCookieをクリアした場合など、あるファーストパーティの他の状態がクリアされたときにはファーストパーティセットの情報も必ずクリアします。

### Service workers

ServiceWorkerはファーストパーティセットを複雑にします。
ServiceWorkerからのネットワークリクエスト、サブリソースの取得など、ServiceWorkerにおいてファーストパーティセットをどのように取り扱うか決める必要があります。

ファーストパーティのオーナーが変更になると、ServiceWorkerはすべてクリアされます。
すなわち、ServiceWorkerはドキュメント同様、特定のファーストパーティセットに限定されます。
ServiceWorkerからのネットワークリクエストは、サブリソースとして動作します。

### UI Treatment

ファーストパーティセットの透明性をユーザに提供するため、ブラウザはファーストパーティセットのオーナーとメンバーの情報をUIに表示することができます。
Chromeであれば[Origin/Page Info Bubble](https://www.chromium.org/Home/chromium-security/enamel/goals-for-the-origin-info-bubble)が考えられます。
この位置は調べたいユーザには必要な情報を与える一方、情報を必要としないユーザに対しては邪魔になりません。
しかし、各ブラウザはそれぞれのUIパターンに基づいて異なる位置に表示することができます。

ファーストパーティセットは、サイトごとのコントロールを`eTLD+1`単位ではなく、ファーストパーティセット単位でグループ化する機会をブラウザに与えます。

## Alternative designs

### Origins instead of registrable domains

ファーストパーティセットはオリジンの集合ですが、Registrable Domain(ドメインから.comや.co.jpなどを除いた部分)で指定されており、[Public Suffix List](https://publicsuffix.org/)に依存しています。
これは提案されている様々なプライバシーモデルやCookieの取り扱いと一致していますが、Web上のセキュリティ境界は、Registrable Domainではなくオリジンです。

代替として、かわりにオリジンによってファーストパーティセットの直接指定が考えられます。
このモデルでは、全てのhttpsオリジンがファーストパーティセットのオーナーになる可能性があります。

既存の動作と互換性を保つために、Registrable Domainを各オリジンのデフォルトのファーストパーティセットとして扱います。
たとえばデフォルトでは`https://foo.example.com`、`https://bar.example.com`、`https://example.com:444`は全て`https://example.com`の所有するセットです。
ファーストパーティセットを明示的に指定することで、このデフォルトのセットを上書きすることができます。

これにより、Public Suffix Listへの依存を減らすことができ、様々な問題が緩和されます。
たとえば大学が学生に任意のサブドメイン`https://foo.university.example`を作ることを許可しておきながら、Public Suffix Listに`university.example`を登録していなかった場合などです。
オリジン指定のファーストパーティセットがあれば、個々のオリジンをデフォルトのセットから切り離すことができ、Cookieのようなオリジンに基づかない機能のセキュリティ問題を回避することができます。
なお、Cookieの`__Host-`プレフィックスでもこの問題に対処することは可能です。

## Prior Art

・Firefoxの[entity list](https://github.com/mozilla-services/shavar-prod-lists#entity-list)
・[draft-sullivan-dbound-problem-statement-02](https://tools.ietf.org/html/draft-sullivan-dbound-problem-statement-02)
・John Wilanderによる[Single Trust and Same-Origin Policy v2](https://lists.w3.org/Archives/Public/public-webappsec/2017Mar/0034.html)および[affiliated domains](https://www.w3.org/2017/11/06-webappsec-minutes.html#item12)


# 感想

広告屋「このファイルを/.well-known/first-party-setに置けばこれまでどおりトラッキング広告出せるよ！」
クライアント「おｋ設置した！」

サードパーティーCookieでは？

悪用されたら対策するとか言ってるけど、悪用されたら対策するってことは対策されるまでは悪用できるってことですよ。

そしてUAポリシーを固めすぎると誰も使えない役立たずな機能になるし、緩めたら悪用の温床です。
しかも最初は使えたとしても、Googleの気分次第でいつ境界を禁じられたりするかわかったものじゃありませんからね。
ブラウザベンダと直接コンタクトできる大手以外はFirst-Party Setsをまともに制御して運用することは難しいでしょう。


ちなみにMozillaはFirst-Party Setsを[harmful](https://mozilla.github.io/standards-positions/)であると評価しており、現在の仕様でFirefoxに実装される可能性はまずありません。
Firefoxですら導入しないということはSafariやVivaldiやBraveには余計に導入されないということであり、First-Party SetsはいつものようにChrome(+もしかしたらEdge)の独自仕様になることでしょう。