Cookie
Cookieはブラウザがパソコンのハードディスクに保存する小さなデータであり、簡易なテキストファイルのこと。 サーバー(Rails)がクライアントに一時的に情報を記録させるときに使用する
Overview
- クッキーとは、変数名とその値のペアのデータのこと
- クッキーはサーバー側で設定して、ブラウザにレスポンスとして送る
- 受け取ったクッキーはブラウザに保存される
- ブラウザが再度そのサイトにアクセスする際、保存されているクッキーをサーバーに送る
- ブラウザ側でクッキーに変数を追加したり、既存の変数の値を変更することもできる
- クッキーには有効期限を設定できる
- クッキーの有効範囲を、ドメインやパスで絞ることができる
- クッキーの有効範囲を、ドメインやパスで絞った場合、そのクッキーを他のドメインやパスのサーバ ーから見ることはできない
Cookieの種類
クッキーには2種類ある
Cookieには1st party Cookieと3rd party Cookieがある。
その違いはCookieの発行元になる。
- セッションクッキー(sessionと共に利用する)
セッションクッキーは、Webサイトにアクセスしている間、ブラウザに一時的に作成され、ユーザーがサイトを離れると、セッションクッキーは削除される。
Expires
やMax-Age
ディレクティブが指定されていないクッキー。クライアントが終了したときに削除される。 - 永続クッキー
永続クッキーはユーザーがブラウザを閉じても削除されず、そのクッキーを作成したWebサイトにアクセスすると再度アクティブになります。永続クッキーは、Cookieのファイル内で設定された期間ブラウザに残る。
Expires
やMax-Age
ディレクティブが指定されたクッキー。クライアントが終了しても削除されない。
1st party Cookie
実際に訪れているサイトのドメインが発行しているのが1st party Cookie
1st party Cookieはユーザーにブロックされにくいという特徴。
そのため、3rd party Cookieに比べてユーザーをきちんとトラッキングすることが可能。
しかし、一方でその ドメインからしか発行できないため、サイトを横断したCookieの付与はできません。
3rd party Cookie
訪れているサイト以外のドメインから発行されているのが3rd party Cookie
たとえば、訪れたサイトにバナー広告が埋まっている場合、そのバナー広告はアドサーバーから配信されています。アドサーバーは訪れているサイトのドメインとは異なるドメインを持っているため、そのCookieは3rd party Cookieになる。
3rd party Cookieはサイトを横断したCookieの付与ができます。そのため、そのユーザーがどのサイトを訪れているかという情報を把握できる。
しかし、近年3rd party Cookieはブラウザによるブロック等の影響で有効期限がすぐに切れてしまうという問題
Cookieの保存期間
これまで Chrome の Cookie の有効期限に制限はありませんでした。1日でも、1か月でも、10年でも Cookie を発行する側の任意で決めることができました。 しかし、2022年8月にリリースされた Chrome 104 以降、Cookie の有効期限は400日を上限とする仕様に変更されました。 Cookie を発行する側が有効期限2年の Cookie を発行しようとしたとしても、ブラウザ側で自動的に400日に短縮されて保存されます
Cookieを保存してはいけない国
とくにEU圏ではこのことが問題視され、GDPRという、Cookieを個人情報として取り扱い、勝手に取得してはいけないという法律まで制定されている。
はい、発行されたクッキーは、そのクッキーが設定されたドメインおよびパスに対してのみ有効です。他のドメインやサイトでは、そのクッキーは送信されません。
クッキーのスコープ
クッキーのスコープは、以下の要素によって決定されます
- ドメイン
クッキーは、設定されたドメインに対してのみ送信される。
たとえば、
example.com
で設定されたクッキーはexample.com
およびそのサブドメイン(sub.example.com
)に対してのみ有効。 他のドメイン(another-example.com
)には送信されません。 - パス
クッキーは、設定されたパスに対してのみ送信される。
/path
で設定されたクッキーはexample.com/path
でのみ有効。 デフォルトでは、ルートパス (/
) が設定され、ドメイン内のすべてのパスに対して有効になります。
タブやサイトの変更
- 同じタブ内でサイトを変更した場合
ブラウザのアドレスバーを使って異なるサイトに移動すると、新しいサイトに対してクッキーは送信されません。クッキーはそれぞれのドメインに対してスコープが設定されているため、異なるドメインに対しては無効です。
ユーザーが
example.com
からanother-example.com
に移動すると、example.com
のクッキーはanother-example.com
には送信されません。 - 異なるタブやウィンドウで同じサイトにアクセスした場合
同じドメインに対して設定されたクッキーは、異なるタブやウィンドウでも有効。
ユーザーが
example.com
を2つの異なるタブで開いた場合、両方のタブで同じクッキーが送信されます。
- クッキーのスコープ: クッキーは設定されたドメインおよびパスに対してのみ有効です。他のドメインやパスには送信されません。
- 同じタブ内でサイトを変更した場合: 異なるサイトに移動すると、新しいサイトには前のサイトのクッキーは送信されません。
- 異なるタブやウィンドウで同じサイトにアクセスした場合: 同じドメインに対して設定されたクッキーは、異なるタブやウィンドウでも有効です。
Cookieのリクエストについて
サーバー側のリクエストでクッキーを明示的に設定する必要がある理由は、以下のような技術的な背景に基づいている。
- クライアントとサーバーの環境の違い ブラウザの自動管理: クライアント側(ブラウザ)では、クッキーは自動的に管理され、同じドメインへのリクエストには自動的にクッキーが含まれる。 これは、ブラウザがHTTPリクエストを生成する際に、適切なクッキーを自動的に追加するため。 サーバーサイドの制御: サーバー側(Node.jsなど)では、HTTPリクエストはプログラム的に生成される。サーバーはクッキーを自動的に管理しないため、開発者が明示的にクッキーを設定する必要がある
- HTTPの仕様 Cookieヘッダー: クッキーはHTTPヘッダーとして送信される。サーバーサイドのリクエストでは、クッキーが自動的に含まれることはない。リクエストを生成する際に、Cookieヘッダーを明示的に設定する必要があるm。
- セキュリティと設計の観点 明示的な制御: サーバーサイドでクッキーを明示的に設定することで、どのクッキーがどのリクエストに含まれるかを正確に制御できます。これはセキュリティとデバッグの観点から重要です。 ブラウザvsサーバー: ブラウザはクッキーを自動的に送信するが、サーバーサイドでは明示的に設定する必要がある。 HTTPヘッダー: サーバーサイドでは、HTTPリクエストのヘッダーとしてクッキーを明示的に追加する必要がある。 セキュリティと制御: クッキーを明示的に設定することで、セキュリティとリクエストの正確な制御が可能になる。
cookieが必要な理由
HTTP通信の問題点
HTTP通信は1回1回の単発の通信なので、接続を維持し続けることができない(ステートレス)
HTTP通信はユーザー識別の仕組みがないのでどのユーザーからの接続かを判別できない。
なので、一連のHTTP通信で、ユーザー接続を維持し続けるには、何かしらの仕組みを実装する必要がある
解決方法 ユーザー認証完了後、サーバー側でユーザー識別子を発行する。 ブラウザへのレスポンスで識別子を送り次回以降ブラウザからサーバーへアクセスする際に、毎回その識別子をサーバーに送ることにより、サーバー側でどのユーザーからのアクセスかがわかるようにする。 そして、その識別子のやり取り方法の1つとして、クッキーを用いる方法がある。
httponlyオプション httponlyは、HTTP通信でのみアクセスできるCookieを生成するためのオプションです。
このオプションを付けると、JavaScriptからのアクセスを完全に遮断でき、サーバーサイドのRailsでしかアクセスできなくなります。 これにより、外部JavaScriptからのCookie盗聴を防ぎます。
- Cookieでも万全ではないことを理解しておく Cookieへの保存は、外部からの攻撃を完全に遮断できるわけではありません。
JavaScriptで参照できるローカルストレージよりはマシなだけであって、Cookieのhttponlyオプションは、あくまで最低限のセキュリティだとお考えください。
Cookieの実装問題点
仕様上、ブラウザ側でクッキーが見られて変更できるのでなりすましができてしまう。
上記の実装問題点解決方法
- サーバー側でユーザーIDではなく、暗号化されたユーザー識別子をクッキーとしてブラウザーに送る
- この暗号化されたユーザー識別子を、一般的に「セッションID」と呼ぶ
- ブラウザからサーバーにアクセスすると、サーバー側では受け取ったクッキーから「セッションID」を取得して、それから「ユーザーID」を復元してユーザーを特定することにより、接続を維持する
- ユーザー識別子は暗号化されているので、他のユーザーのユーザー識別子を生成してなりすますのは困難
サブドメインでcookieを共有する
クロスオリジン通信でのCookie共有設定
クロスオリジン通信でのCookie共有は双方に設定が必要。
credentials(クレデンシャル) リクエストヘッダーのwithCredentials(ウィズ クレデンシャル)フラグをtrueにする。 withCredentialsは、クロスオリジンのクライアント資格情報を使用して、リクエストを行うことを許容するか否かを設定するフラグです。(デフォルトはfalse)
trueにすることで、 クロスオリジンリクエストの際に、Cookieを送信でき、クロスオリジンレスポンスのCookieを受け取ることができます。
クッキー(Cookie)とセッションの違い
小括として、クッキーとセッションの違いをまとめておきましょう。 クッキーもセッションも情報を保存するために使用されることには違いがありません。 違いとしては保存場所が挙げられます。クッキーはクライアント側のマシン(主にブラウザ)にのみ保存され、セッションはブラウザだけでなく、サーバーにも情報が保存されます。 また、保存の期間にも大きな違 いがあり、セッションはユーザーがブラウザを閉じるか、サイトを離れると情報が削除されます。一方、クッキーには永続クッキーがあり、情報を保持し続けます。 さらに、大きなポイントとしてはセッションは無効にできませんが、クッキーは無効にできる。
Set-Cookie
Set-CookieはHTTPのレスポンスヘッダーで、サーバーからユーザーエージェントへクッキーを送信するために使用され、ユーザーエージェントはそれを後でサーバーに送り返すことができるようになる。
複数のクッキーを送信するには、複数のSet-Cookieヘッダーを同じレスポンスで送信してください。
cookie それぞれのプロパティ
ウェブサーバーとウェブブラウザとの間でやりとりできる小さなデータとして「クッキー (Cookies)」というものがあります。このクッキーは属性を持たせることができるのですが、その中にはセキュリティを高めるための属性がいくつかあります。
Secure
Secure 属性がついたクッキーは HTTPS プロトコル上の暗号化されたリクエストでのみサーバーに送信され、安全でない HTTP では決して送信されない
SameSite
参考URL
Chrome で SameSite=None に関する Cookieについての警告が表示される
Domain属性が、「サーバ → クライアント」のクッキーの送信条件を定義するのに対して、SameSite
は「クライアント → サーバ」のクッキーの送信条件を制御する。
具体的には、クロスサイトリクエストでクッキーを送信するかどうかを制御し、CSRFに対するある程度の防御を提供する。
Chrome SameSite
Chromeがデフォルトでクッキーを SameSite = Lax
として扱うようになる
クロスサイトな状況でクッキーを発行させたい場合(埋め込みコンテンツなど)は、SameSite属性にNoneという値をセットする。
これで、クロスサイトでもクッキーが発行されます。そして警告にもあったように、この場合は必ずSecure属性もつける
つまり今後、httpでクロスサイトなクッキーを発行してはいけないということです。
SameSiteには3つの設定を行うことが可能で、None、Lax、Strict
の3つとなる。
※これはセキュリティレベルの高さの指定になる
- None(なし)
- Lax(緩い)
- Strict(厳しい)
上記の順番でセキュア(CSRF)に対するセキュリティレベルを示している。 仕様が変更にある前まではSameSiteを指定していない場合、ブラウザ側ではNone(なし)として判断してWebサイトからのCookieの利用を許可しておりましたが、今回のGoogle Chrome 80からはSameSiteを指定しない場合、Lax(緩い)として取り扱う形となった。
Strict
ブラウザーが同一サイトのリクエストに対してのみクッキーを送信する。
Lax
クロスサイトリクエスト(画像やフレームを読み込むリクエスト)ではクッキーを送信しない。
ユーザが外部サイトから元のサイトに戻る時(たとえば、リンクをたどる時)にはクッキーを送信する。
SameSiteが設定されていない時のデフォルトの動作。
None
ブラウザーがクロスサイトと同一サイトの両方のリクエストでクッキーを送信する。 同時に、Secure属性も設定する必要が ある(例:SameSite=None; Secure)。
SameSiteなどの回避方法
Chrome84からCookieの属性であるSameSiteのデフォルト値がNoneからLax変更されたことにより、異なるオリジン間でCookieが受け取れなくなっていた。 明示的にSameSite=Noneを設定することでCookieを受け取れるようにはなるが、そうすると次はCookieの属性であるSecureも必須となる。
対応内容
ローカル環境をSSLする必要があるのかと思ったらdevserverのproxyオプションで解決した。 同一オリジン扱いになるのでCORS問題も解決できそう。
つまりproxyを立てて通信を行う(local)、devでも行う必要があるのか気になる。
Next Http Proxy Middlewareで Next.js × Rust間のリクエストをproxyする
HttpOnly
HttpOnly属性は、サーバー側で付与してCookieを送信することで、JavaScriptからCookieにアクセスを行えなくするためのもの。
ここ最近の主要ブラウザはサポートしている。そのためCookieに保存することが推奨されている(JWT)
Domain
Cookieのセキュリティ周りでいちばんややこしいDomain属性をしっかり理解する
このオプションを設定しない場合は同一のオリジンでのみ利用可能なクッキーとなる。
このオプションを設定した場合は、そのドメイン(たとえば nicovideo.jp
)と、そのサブドメイン(たとえば live.nicovideo.jp
)でも利用可能なクッキーとなる。
また、nicovideo.jp
のページ上で domain=google.com
のようにホスト名が異なるクッキーを設定することはできない(設定しても無視される)
しかし、 www.nicovideo.jp
のページ上で domain=nicovideo.jp
というクッキーを設定することは可能。
そうした場合、そのクッキーは nicovideo.jp
内のどんなサブドメインからでもアクセスが可能になる。
このように、 domainオプションを指定することによって、サブドメインが異なるサービスでもログインセッション情報などを気軽に共有することが可能です。逆に、指定がない場合はサブドメインが違えば共有できない
以前は domain=.nicovideo.jp
のように、プレフィックスにドットを置くことで「サブドメインを含めて利用可能」と明示することとする場合があったようですが、現在はプレフィックスにドットを置いても無視される仕様となっている。
※http://localhost:8080/
の場合は、この「ドメインの一致」を見る部分は localhost:8080
つまりポート番号まで含まずRFCではポート番号では分離されないと記載がある。
2. Domain
属性と withCredentials
の違い
Domain
属性は、クッキーがどのドメインに対して有効であるかを指定します。この属性を設定することで、クッキーを複数のサブドメイン間で共有すること可能になる。
domain=example.com
: example.com
とそのすべてのサブドメイン(例:sub.example.com
)に対してクッキーが有効になる。
withCredentials
withCredentials
は、クロスオリジンリクエストでクッキーや認証情報(セッションIDなど)を含めるために使用されます。この設定が有効になっている場合、リクエストと一緒にクッキーが送信されます。
Domain
属性: クッキーの適用範囲をドメイン全体やサブドメインに広げるために使用。withCredentials
: クッキーや認証情報をクロスオリジンリクエストに含めるために使用。
これにより、各属性の役割と違いが明確になると思います。どちらを使うかは、特定のユースケースに依存します。
Cookie expires時間
Cookieの法定タイムゾーン はGMT(グリニッジ標準時)と決められており、expiresはGMTで保存されます。 また、有効期限を判断するために使用されるタイムゾーンもGMTです。 GMTは日本時間マイナス9時間で、UTC(世界標準時)と一致します。
Cookie同意画面が必要な理由
GA4を使うのにcookie同意ポップアップは結局必要なのか
クッキーの確認画面を表示する必要性については、利用するクッキーの種類やデータ処理の内容によって異なります。以下は、クッキー同意が必要かどうかを判断するための一般的なガイドラインです。
クッキー同意が必要な場合
- 個人データの処理 クッキーを使用して個人データ(名前、メールアドレス、IPアドレスなど)を収集、処理、または共有する場合は、同意が必要です。
- トラッキングクッキー 行動追跡やプロファイリングのために使用されるクッキー(例:広告ターゲティングクッキー)は、同意が必要です。
- サードパーティクッキー サードパーティが提供するクッキーを使用してデータを収集する場合、同意が必要です。
クッキー同意が不要な場合
-
技術的に必要なクッキー ウェブサイトの基本的な機能を提供するために必要なクッキー(例:ショッピングカート内の商品を記憶するクッキー)は、同意が不要です。
-
セッションクッキー 一時的に使用され、セッションが終了すると削除されるクッキー(例:ユーザーのログイン状態を維持するクッキー)は、同意が不要です。
利用規約やプライバシーポリシーでの同意
利用規約やプライバシーポリシーにクッキー使用の情報を含めることは重要ですが、ユーザーに明確な同意を求めるためには、ポップアップやバナー形式での通知が推奨されます。これにより、ユーザーはクッキーの使用について適切に通知され、選択の機会が与えられます。
クッキー同意画面を表示するための基準
-
クッキーの種類を特定する:
- 使用しているクッキーが技術的に必要なものか、それとも個人データを処理するものかを特定します。
-
データ処理の内容を確認する:
- 個人データの収集や第三者とのデータ共有がある場合、クッキー同意画面が必要です。
-
法規制の確認:
- GDPRやCCPAなど、該当するプライバシー規制に従い、ユーザーの同意が必要かを確認します。