CookieのDomainとSameSiteについて、毎回調べて思い出す必要があったので、自分用にまとめる。
以下、属性の並びは、mdn web cocs (Set-Cookie) に従う。
上記のドキュメントを読めば簡単に理解出来るもの(DomainとSameSite以外)は、説明を割愛するが、一部記載がある場合もあり。
Expires=<date> (省略可)
割愛
- 「セッションクッキー」と「永続的クッキー」について
- セッションクッキー(Session Cookie)
- Expires や Max-Age ディレクティブが指定されていないクッキー。クライアントが終了したときに削除される。
- 永続的クッキー(Permanent Cookie)
- Expires や Max-Age ディレクティブが指定されたクッキー。クライアントが終了しても削除されない。
- セッションクッキー(Session Cookie)
Max-Age=<number> (省略可)
割愛
Domain=<domain-value> (省略可)
- クッキーを送信する先のホスト(つまり、クッキーの受け手)を定義する。
- 省略した場合は、クッキーを送信するサーバのホスト名になり、サブドメインは含まれない。
- つまり、何も指定しないのが、セキュリティ面で一番強固。
- ドメインを指定した場合は、すべてのサブドメインが常に含まれる。
- ドメイン名の前のドット (
.example.com) は無視される。- 設定は可能だが、
.example.comもexample.comもクッキーを送るドメインの範囲は同じ。
- 設定は可能だが、
- ドメイン名の前のドット (
- 複数の値を設定することは出来ない。
- 無効な(ユーザーエージェントに拒否される)設定の例
- オリジンのサーバーを含まないドメインに所属するクッキーは、ユーザーエージェントが拒否する。
-
Domain=somecompany.co.ukをoriginalcompany.comでホスティングされたサーバーから設定しようとすると拒否される。以下原文の例では、オリジンがfoo.example.comで、example.comやfoo.example.comを設定した場合は問題ないが、bar.example.comやbaz.foo.example.comを設定した場合はユーザーエージェントが拒否する。 -
原文(以下、抜粋)
- The user agent will reject cookies unless the Domain attribute
specifies a scope for the cookie that would include the origin
server. For example, the user agent will accept a cookie with a
Domain attribute of "example.com" or of "foo.example.com" from
foo.example.com, but the user agent will not accept a cookie with a
Domain attribute of "bar.example.com" or of "baz.foo.example.com".
- The user agent will reject cookies unless the Domain attribute
-
- 提供するドメインのサブドメインへのクッキーは拒否される(上記の説明に包含されるが、念の為記載)。
-
Domain=foo.example.comをexample.comでホスティングされたサーバーから設定しようとすると拒否される。
-
- オリジンのサーバーを含まないドメインに所属するクッキーは、ユーザーエージェントが拒否する。
Path=<path-value> (省略可)
https://www.javadrive.jp/javascript/webpage/index18.html の「Cookieを送信するパス(Path属性)」を参照。
Secure (省略可)
割愛
HttpOnly (省略可)
割愛
SameSite=<samesite-value> (省略可)
-
Domain属性が、「サーバ → クライアント」のクッキーの送信条件を定義するのに対して、同属性は「クライアント → サーバ」のクッキーの送信条件を制御する。 - 具体的には、クロスサイトリクエストでクッキーを送信するかどうかを制御し、CSRFに対するある程度の防御を提供する。
- cross-site(クロスサイト)の定義について(参考)
- same-site(同一サイト)の定義は、「スキーム(
http://部分)」及び、セカンドレベルドメイン(example.com の example)とトップレベルドメイン(example.com の com)のコンビネーションで判断される。例えば、https://foo.example.com と https://bar.example.com や https://one.two.example.com は同一サイトとみなされる。 - 上記以外が、クロスサイトとみなされる。
- 但し、ここに書かれている通り、PUBLIC SUFFIX LISTというのがあり、ここに載っているサイトは、上記のルールで同一サイトであるとみなされても、クロスサイトとみなされる。
- 例えば
my-site.azurewebsites.netとyour-site.azurewebsites.netは、クロスサイトとみなされる。
- 例えば
- same-site(同一サイト)の定義は、「スキーム(
以下、設定可能な値。
Strict
- ブラウザーが同一サイトのリクエストに対してのみクッキーを送信する。
Lax
- クロスサイトリクエスト(画像やフレームを読み込むリクエスト)ではクッキーを送信しない。
- ユーザが外部サイトから元のサイトに戻る時(例えば、リンクをたどる時)にはクッキーを送信する。
-
SameSiteが設定されていない時のデフォルトの動作。
None
- ブラウザーがクロスサイトと同一サイトの両方のリクエストでクッキーを送信する。
- 同時に、
Secure属性も設定する必要がある(例:SameSite=None; Secure)。
参考文献
- https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Set-Cookie
- https://www.javadrive.jp/javascript/webpage/index18.html
その他(SPA時の、クライアントとサーバのドメイン名についての考察)
-
Domainの仕様(オリジンのサーバーを含まないドメインに所属するクッキーは、ユーザーエージェントが拒否する)を考えると、同じドメインである必要がある。 - (上記の条件で十分だが)、
SameSiteの仕様も考慮して、SPAの場合、サーバとクライアントのドメインを揃える(api.example.com,www.example.com等)。そうすれば、Strictが設定できる。
開発環境についての補足
前提
- 本番環境はSSL通信前提だが、SPAの開発環境でSSL通信ができない場合がある。
- ドメイン名は以下の通り。
- サーバ: api.example.com
- フロントエンド: front.example.com
考察
「スキーム(http://部分)」が異なると、same-site(同一サイト)とみなされない。
つまり、フロントエンドとサーバが「両方非SSL」or「両方SSL」で揃っていれば、非SSL(secure属性なし)でも通信可。よって、サーバへのアクセスを非SSLで行えば解決(しそうだが、試したことはない)。