CookieのSameSite Attributeとは？
Published: 2020-04-03 14:26:41

---
title: CookieのSameSite Attributeとは？
published: true
date: 2020-01-15 00:00:00 UTC
tags: 
canonical_url: https://blog.tomoyukikashiro.me/post/ja/what-is-samesite-cookie/
---

Cookie に SameSiteという新しい属性が追加されて、いくつかのブラウザではその初期値が変わる予定です。

Google Chrome ではその変更が2020年2月を予定しています。  
複数のドメインの間で通信をし、Cookieを利用するサービスは影響あるかもしれません。

ここでは、 SameSite の概要と影響をさくっと確認していきます。

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#samesite-cookies-%E3%81%A8%E3%81%AF%EF%BC%9F)SameSite Cookies とは？

SameSite とは、 Cookie に追加される新しい属性です。  
Cookie を発行する際は、 key=value と合わせて、属性として Cookie の振る舞いを制御するオプションを設定できます。  
例えば、

- Expires : Cookieの有効期限
- Secure : https の場合のみ利用を制限するかどうかのフラグ
- HttpOnly : サーバサイドでの利用に制限するかどうかのフラグ

などです。

SameSite は Cookie がドメインをまたいで利用されるときの挙動を制御する新しいオプションになります。  
SameSite=Strict, SameSite=Lax, SameSite=None の3つの値から選択できます。  
詳しい内容は後述します。

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#samesite-cookie-%E3%81%8C%E5%BF%85%E8%A6%81%E3%81%A8%E3%81%95%E3%82%8C%E3%82%8B%E7%90%86%E7%94%B1)SameSite Cookie が必要とされる理由

主な理由は、 CSRF（クロスサイトリクエストフォージェリー）という攻撃を防ぐことにあります。

例えば、SNSなどでコメントを投稿する機能を例に考えます。  
コメントを投稿するのに必要な仕様は以下だとします。

- method : post
- URL : example.com/comments
- parameter : body (コメント内容)
- 条件 : ログイン必須（cookieを使って認証管理）
- 方法 : `<form>` タグを利用して送信

HTMLはこんな感じ。

```
<!-- example.com でのコメント投稿機能 -->
<form method="POST" action="https://example.com/comments">
  <textarea placeholder="コメントを入力" name="body" rows="5" cols="33">
  <button>コメント送信</button>
</form>
```

もし、アクセスしたユーザーがログイン済みであれば、コメント投稿は成功します。  
しかし、この実装のままだと、関係ないサービスからでもコメント投稿が成功してしまいます。  
例えば、

```
<!-- example.net （.netなので無関係のサイト）からの、example.com のコメント投稿機能を悪用したいたずら -->
<form style="display: none;" method="POST" action="https://example.com/comments">
  <textarea value="だれかの悪口。だれかの悪口。だれかの悪口。だれかの悪口。だれかの悪口。だれかの悪口。だれかの悪口。">
  <button>コメント送信</button>
</form>
```

このような実装で、ユーザーの意思とは関係なく、このformをsubmitすることで、そのログインユーザーのコメントとして投稿されてしまいます。  
これがクロスサイトリクエストフォージェリーという攻撃です。

tokenを使ってリクエストが example.com からであるかどうかを確認する方法でこの攻撃を防ぐのが、よく見る対応です。  
この攻撃は、別のサイトからの意図しないリクエストであっても cookie 込みで送信されるという cookie の仕様を利用（悪用）した方法とも言えます。

SameSite 属性を利用することで、 `関係ないサイト => example.com` へのリクエスト時に、cookie 込みで送信するかどうかを example.com 側で制御できるようになり、結果としてクロスサイトリクエストフォージェリー対策になります。

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#samesite-%E3%81%AE%E7%A2%BA%E8%AA%8D%E6%96%B9%E6%B3%95)SameSite の確認方法

Chrome DevToolsで確認可能です。  
方法は2つあります。

### [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%BF%E3%83%96)ネットワークタブ

Cookieが付与されているドメインのリクエストをネットワークタブで見つけ、詳細内の、 `Cookiesタブ` で確認可能です。

### [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%BF%E3%83%96)アプリケーションタブ

アプリケーションタブの `Storage` > `Cookies` でドメイン毎に確認可能です。

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#%E3%83%87%E3%83%A2%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E7%A2%BA%E8%AA%8D)デモを使って確認

さっそく、 SameSite を指定した Cookie がどのようになるのかデモとともにみていきます。  
ここでは、サイトA（背景色が白）とサイトB（背景色がグレー）の２つのサイトで、3つのリクエストを例に見ていきます

- サイトAからサイトBへの画面遷移
- サイトAでiframeを使って、サイトBを表示する際のリクエスト
- サイトAからサイトBへのXHR

サイトBには、 `test=test` という Cookieが付与されています。  
サイトBを表示（リクエスト）する際、 `test=test` のCookieが読み取れれば画面に表示し、読み取れなければ、 `test=` と表示します。

Cookieを設定する際、 `SameSite` のオプションを変えて、上記3つのリクエストでCookieの読み取りにどんな違いがでるか見ていきます。

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#%E3%83%87%E3%83%A2%E7%B5%90%E6%9E%9C)デモ結果

サイトBでCookieの中身を読み取れるか？

| sameSite | ページ遷移 | iframe | XHR |
| --- | --- | --- | --- |
| strict | ❌ | ❌ | ❌ |
| Lax | ⭕ | ❌ | ❌ |
| None | ⭕ | ⭕ | ⭕ |

[https://samesite-cookie.web.app/](https://samesite-cookie.web.app/)

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#samesite%E3%81%AE%E5%88%A9%E7%94%A8%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3)SameSiteの利用パターン

認証管理に例して考えるなら、、、

### [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#cookie%E3%81%A7%E8%AA%8D%E8%A8%BC%E7%AE%A1%E7%90%86%E3%81%97%E3%81%A6%E3%81%8A%E3%82%8A%E3%80%81%E5%88%A5%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%81%8B%E3%82%89%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%82%92%E8%A1%8C%E3%82%8F%E3%81%AA%E3%81%84%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9)Cookieで認証管理しており、別ドメインからリクエストを行わないサービス

SameSiteを利用することで、クロスサイトリクエストフォージェリーの攻撃を防ぐことができるので、可能な限り、 `SameSite=Strict` や `SameSite=Lax` の利用をしていきたいとこです。

### [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#cookie%E3%81%A7%E8%AA%8D%E8%A8%BC%E7%AE%A1%E7%90%86%E3%81%97%E3%81%A6%E3%81%8A%E3%82%8A%E3%80%81%E5%88%A5%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%81%8B%E3%82%89%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%82%92%E8%A1%8C%E3%81%86%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9)Cookieで認証管理しており、別ドメインからリクエストを行うサービス

`SameSite=Strict` や `SameSite=Lax` を利用すると別ドメインからのリクエストでは、ログイン済みでも、Cookieが付与されて送信されないため、未ログインとして扱われてしまします。

また、Chrome, Firefox, Edgeでは SameSite が未指定の場合 `SameSite=Lax` として扱うことを検討しており、 Chrome version 80で 未指定の場合、 `SameSite=Lax` として扱い変更がリリースされる予定です。

よって、何も対応してないと、2020年2月の Chrome version 80 のリリースのタイミングでこのケースのサービスでは Chrome で `ログインできない` 不具合が発生します。  
今まで同じ挙動にするためには、 `SameSite=None` と `Secure` のオプションを Cookie に設定する必要があります。

### [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#%E5%BF%98%E3%82%8C%E3%81%8C%E3%81%A1%E3%81%AA%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E3%81%AE-chrome-extension)忘れがちなパターンの Chrome extension

別ドメインでリクエストが発生する忘れがちなパターンに Chrome extension があります。  
もし Chrome extension を開発している場合は、 2020年2月の Chrome version 80 のリリースのタイミングでトラブルにならないように確認しておきましょう。

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#samesite%E6%9C%AA%E6%8C%87%E5%AE%9A%E3%81%AE%E5%A0%B4%E5%90%88%E3%80%81samesitelax%E3%81%A8%E3%81%97%E3%81%A6%E6%89%B1%E3%82%8F%E3%82%8C%E3%82%8B%E3%81%93%E3%81%A8%E3%81%AE%E7%A2%BA%E8%AA%8D%E6%96%B9%E6%B3%95)SameSite未指定の場合、SameSite=Laxとして扱われることの確認方法

[https://youtu.be/QSKky-bkTQ8?t=324](https://youtu.be/QSKky-bkTQ8?t=324)