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で行えば解決(しそうだが、試したことはない)。