Open1

CookieやJWTなどの認証方法

yamazakingyamazaking

Cookie

https://developer.mozilla.org/ja/docs/Web/HTTP/Cookies

サーバーがユーザーのウェブブラウザーに送信する小さなデータです。

Cookieの用途

サーバーはHTTP Cookieのコンテンツを使用して、さまざまなリクエストが同じブラウザー/ユーザーから送られたものかを判断する

主な用途としては次の3つ

  • セッション管理
  • パーソナライズ(表示言語やUIテーマなどのユーザー設定)
  • トラッキング

なお、ウェブの初期のころではCookieはクライアント側のストレージとして使用されていたが、ストレージの制限や、リクエストのたびに送信されてしまうなどのデメリットがあるため、基本的にはローカルストレージなどを使用するほうがいい

簡単な例:

  1. ユーザーがログイン情報をフォームからサーバーに送信
  2. サーバーはログイン情報を確認し、正しければブラウザ上のログイン状態を記録するセッションIDを含むクッキーを返す
  3. ユーザーが同サイト別ページに移動する。ブラウザーは、ユーザーがまだサインインしていると認識しているのを示すまえに、セッションIDを含むクッキーを、対応するリクエストとともに送信する
  4. サーバーはセッションIDををチェックし、有効であればユーザーに新しいページを送信。無効であれば、セッションIDは削除され、ユーザーにはログイン用の画面を表示しない。

Cookieの作成、削除、更新

作成

HTTPヘッダーにSet-Cookieを一つまたは複数いれて、送信することでクッキーをセットできる

Set-Cookie: <cookie-name>=<cookie-value>

新しいリクエストが行われると、ブラウザーは通常HTTPヘッダー内のCookieで前回格納されたCookieを現在のドメイン用にサーバーに送信します。

削除

有効期限日または期間を指定すると、それ以降はCookieが削除され、送信されなくなる。

Expires:指定日時を過ぎると削除
Max-Age指摘期間が経過したあとに削除

Max-Ageのほうがエラーの可能性が低く、Expiresと両方設定されるときはMax-Ageが優勢される。

Expires,Max-Ageが指定されていないCookieの場合は、セッションCookieといい、現在のセッションが終了すると削除される。

更新

サーバーは既存のCookieの名前と新しい値を指定したSet-Cookieヘッダーを送信する。(新規作成するのと同じ)

ブラウザーでは、JavaScript を使用して Document.cookie プロパティ、または非同期の Cookie Store API を使用して新しい Cookie を作成することができる。

document.cookie = "yummy_cookie=choco";
document.cookie = "tasty_cookie=strawberry";

Security

Cookieが悪意のある第三者からの攻撃を考慮しなければならない。

Cookieへのアクセスをブロック

Cookieが安全に送信され、意図しない第三者やスクリプトからアクセスされないようにするには、Secure属性とHttpOnly属性の2つがある

Set-Cookie: id=a3fWa; Expires=Thu, 21 Oct 2021 07:28:00 GMT; Secure; HttpOnly
  • Secure:HTTPSプロトコル上の暗号化されたリクエストでのみサーバーに送信される。安全ではないHTTPでは決して送信されないため、中間者攻撃の攻撃者が簡単にアクセスすることはできない。httpの安全ではないサイトは、Secure属性を使用してCookieを設定することはできない。
  • HttpOnly:JavaScriptのDocument.cookieAPIでアクセスすることはできない。XSSを緩和するのに役立つ

Cookie送信先の定義

Domain および Path 属性は、Cookie の「スコープ」、つまり Cookie を送信する対象の URL を定義します。

  • Domain属性:Cookieを受診することができるサーバーを指定する。指定された場合、指定したサーバーとサブドメインでCookieが使用できる。
    Domainが指定されていない場合は、Cookieはそれを設定したサーバーでは利用できるが、そのサブドメインでは利用できない。Domainを設定できるのは、自分自身で管理するドメインまたは親ドメインのみ。サブドメインでは設定できない。例えば、ドメインが foo.example.com のサーバーは、この属性を example.com または foo.example.com に設定することはできますが、bar.foo.example.com や elsewhere.com には設定できません(ただし、bar.foo.example.com などのサブドメインには Cookie が送信されます)。
Set-Cookie: id=a3fWa; Expires=Thu, 21 Oct 2021 07:28:00 GMT; Secure; HttpOnly; Domain=mozilla.org
  • Path属性:Cookieヘッダーを送信するためにリクエストされたURLの中に含む必要があるURLのパス
Set-Cookie: id=a3fWa; Expires=Thu, 21 Oct 2021 07:28:00 GMT; Secure; HttpOnly; Path=/docs

SameSite属性によるサードパーティCookieの制御

SameSite 属性は、サーバーがサイト間リクエストとともに Cookie を送信するかどうか、すなわちサードパーティ Cookie を送信するかどうかを指定する。サイト間リクエストとは、サイト(登録されているドメイン)やスキーム(http または https)がユーザーが現在いるサイトと一致しないリクエストのことです。これには、他のサイト上のリンクがクリックされて自分のサイトに移動する際に送信されるリクエストや、埋め込みサードパーティコンテンツによって送信されるリクエストが含まれる。

SameSite は、情報の漏洩を防止し、ユーザーのプライバシーを保護し、クロスサイトリクエストフォージェリー攻撃に対していくらかの防御となります。取ることができる値は Strict, Lax, None の 3 つです。

Strict

ブラウザーが Cookie の発行元サイトからのリクエストに対してのみ、レスポンスで Cookie を送信するようにします。これは、認証やショッピングカート情報の格納など、常に最初のナビゲーションの後に来る機能に関連する Cookie がある場合に使用すべきです

Set-Cookie: cart=110045_77895_53420; SameSite=Strict

Lax

ユーザーが Cookie の発行元サイトに移動(ユーザーが別のサイトから移動してくる場合でも)した際にも、ブラウザーが Cookie を送信します。これは、サイトの表示に影響を与える Cookie に役立ちます。例えば、ウェブサイトにアフィリエイトリンク付きの提携製品情報を持たせることができます。そのリンクで提携サイトに移動すると、アフィリエイトリンクを辿ったことを示す Cookie を設定し、報酬バナーを表示したり、製品購入時に割引を指定したりすることができる。

Set-Cookie: affiliate=e4rt45dw; SameSite=Lax

None

Cookie が元のサイトとサイト間のリクエストの両方で送信されることを指定します。これは、例えば広告技術や分析ツールのプロバイダーなど、他のサイトに埋め込まれたサードパーティのコンテンツから送信されたリクエストとともに Cookie を送信したい場合に便利です。SameSite=None が設定されている場合、Secure 属性も設定する必要があることに注意してください。SameSite=None では、安全なコンテキストが要求されます。

Set-Cookie: widget_session=7yjgj57e4n3d; SameSite=None; Secure; HttpOnly

Cookieの接頭辞

Cookie の仕組みの設計上、サーバーは、Cookie が安全なオリジンから設定されたことを確認することはできず、Cookie が元々どこで設定されたのかを見分けることさえできない。

Cookieの接頭辞を利用することで、Cookieでの設定を制限できる。
次の2つの接頭辞がある。

__Host-

Set-Cookieヘッダーが受け入れられのは、Secure属性で指定され、安全なオリジンから送信されており、Domain属性を含んでおらず、Path属性が/に設定されている場合のみ。この場合、これらのCookieは「ドメインにロックされている」とみなすことができる

__Secure-

Set-Cookiディレクティブが受け入れられ宇野は、Secureであり、安全なオリジンから送信されている場合のみ。

これらの接頭辞がついていて、制約に適合していないCookieは、送られてもブラウザーが拒否する。これにより、仮にサブドメインで接頭辞のついたCookieを作成した場合、サブドメインに限定されるか、完全に無視されるかとなる。
アプリケーション・サーバーは、ユーザーが認証されているか、あるいはCSRFトークンが正しいか銅かを判断するときに、特定のCookie名をチェックするだけなので、これはセッション固定化に対する防御手段として効果的に機能する。