やりたかったこと
以下の条件を満たすアプリケーションでCookieを設定したい
- フロントサイト(ブラウザのナビゲーションバー)のURLとバックエンドのURLが異なる
- フロントサイトからはAjaxによるリクエストを送信し、サーバーは
REST API
を返却するSPAアプリケーションの構成
発生した(解決したかった)現象
Ajaxリクエストのレスポンスで Cookie が設定できない。
Chrome のデベロッパーツールを使用しても特にエラーは出力されないが、なぜか_Cookie_が設定されない。
結論
時間のない方は結論の部分だけ設定してみて下さい。
以下を設定することでクロスサイトでCookieを設定する事ができる
- フロントアプリケーションの設定
-
XMLHttpRequest.withCredentials
にtrue
を設定する[^1]
-
- バックエンドアプリケーションの設定
- レスポンスヘッダーに
access-control-allow-credentials
にtrue
を設定する[^2] - レスポンスヘッダーに
access-control-allow-origin
でフロントアプリケーションのURLを設定する[^3]- ['localhost:4000', "*"]の様な値でOK。ワイルドカードのみではいけない
- Cookieを設定する際に
SameSite
ポリシーをNone
にする[^5]
- レスポンスヘッダーに
XMLHttpRequest.withCredentials[^1]
XMLHttpRequestは**別のドメインからのCookieをデフォルトでは受付けていません。**
ただし、withCredentialsにtrueを設定している場合、Cookieを受け付けることが出来ます。
また、この設定は同じサイトのリクエストには影響を与えません。
なので、開発環境だけクロスサイトになる様な環境でも特に考慮せずに利用できます。
Mozillaの解説
XMLHttpRequest from a different domain cannot set cookie values for their own domain unless withCredentials is set to true before making the request
access-control-allow-credentials[^2]
リクエストにCredentials
の設定が含まれている場合に、レスポンスをJavaScript
に教えるかどうかを指示するもの
access-control-allow-origin[^3]
指定されたOriginからのリクエストを受け付けることが出来るかを表すもの
ただし、ワイルドカードを指定した場合はCredentials
の設定はサポートされない[^4]
SameSite policy[^5]
- Lax
- モダンブラウザーのdefaultのポリシー
- 以下の何れかの場合にCookieの送信が許可される
- トップレベルナビゲーション(ブラウザーのナビゲーションバー)と同一の場合
- GETリクエストの場合
- Strict
- トップレベルナビゲーション(ブラウザーのナビゲーションバー)と同一の場合のみ送信される
- None
- Cookieは全ての状況で送信される
今回実験している中で分かったこととしては、サブドメインの場合にStrict
を設定してもブラウザーにCookieを設定することは出来る。また、Cookieの送信も行われる。
トップレベルナビゲーションのURLとDomainが異なる場合、None
のポリシーの場合しかCookieを設定することは出来ない。
Lax
とStrict
はクロスサイトではブラウザーにCookieを設定することができないポリシーとなる。
[^1]https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
[^2]https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials
[^3]https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
[^4]https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSNotSupportingCredentials
[^5]https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite