Cookie の SameSite 属性について

こんにちは、フロントエンドエキスパートチームの小林(@koba04)です。

フロントエンドエキスパートチームでは、日々の業務としてブラウザやライブラリの更新情報をキャッチアップして社内で共有しています。

例えば先日、CSSのプロパティである image-orientation のデフォルト値が none から from-image に変わったため、画像の Exif 情報の扱いが変更されました。

https://www.fxsitecompat.dev/ja/docs/2020/jpeg-images-are-now-rotated-by-default-according-to-exif-data/

注: Firefox では COVID-19 の影響により、この変更は延期されました。(Chrome は予定通り 81 で リリースしています)

https://blog.chromium.org/2020/02/chrome-81-near-field-communications.html

このような変更はプロダクトに影響があるため、フロントエンドエキスパートチームでは社内の kintone に専用のスレッドを作成し、変更点などを整理して伝えています。

f:id:cybozuinsideout:20200430182958p:plain
Browser backward compatiblity / ブラウザ後方互換性情報

上記は実際の投稿の一部であり、以降に変更の詳細などを記載して取るべき対応について記載しています。 これらの情報の多くは社外にも公開可能なため、今回は Cookie の SameSite 属性について書きます。

今回確認するために使用したブラウザのバージョンはそれぞれ下記の通りです。

  • Chrome 81
  • Firefox 75
  • Safari 13.1

SameSite 属性とは

Cookie に指定可能な新しい属性です。 Chrome, Firefox, Safari の全ブラウザですでに実装されています。仕様は現在 Internet Draft の状態です。

https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-06

SameSite 属性には、次の値が指定できます。

None

これまでの Cookie の挙動通り、全ての cross-site なリクエストに対して Cookie が付与されます。

Strict

same-site に対するリクエストにのみ Cookie が付与されます。Cookie を使いログイン認証をしているサイトに対して cross-site なサイトに設置されたリンクから遷移した場合、リクエストに Cookie が付与されないため未ログイン状態になります。これは CSRF の攻撃に対しても有効ですが、ユーザーは cross-site なサイトからログインした状態で遷移できないため、ユーザーは再度ログイン処理や再読み込みが必要となります。

Lax

NoneStrict の間に位置するような指定です。cross-site を含むページ遷移のようなトップレベルのナビゲーションと、same-site のスクリプトや画像などのサブリソースに対するアクセスに対してのみ Cookie が付与されます。したがって cross-site のサブリソースに対するリクエストには Cookie が付与されません。ただし Lax の場合には、Strict と異なり cross-site なトップレベルのナビゲーションに対しては Cookie が付与されるため、ログインした状態で遷移できます。ただし、POST メソッドのような unsafe な HTTP メソッドによる cross-site なトップレベルのナビゲーションに対して Cookie が付与されません。したがって、POST メソッドなどを使ったフォームのサブミットに対する CSRF の攻撃に対しても有効です。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_cookies

上記で言及した same-site や cross-site については、下記の記事がとてもわかりやすいのでオススメです。

https://web.dev/same-site-same-origin/

SameSite 属性のデフォルト値を Lax にする流れ

Chrome や Firefox では、この SameSite 属性のデフォルト値を None ではなく Lax に変更することを計画しています。 Chrome ではすでに SameSite 属性のデフォルト値を Lax にする変更を Chrome 80 から段階的にロールアウトしていました。 ただ、COVID-19 の影響を鑑みてロールアウトを一旦中止することを発表しています。

https://blog.chromium.org/2020/04/temporarily-rolling-back-samesite.html

Chrome の最新の状況については下記ページで確認できます。

https://www.chromium.org/updates/same-site

また、Firefox でも同様に Lax をするデフォルト値にするための作業が進められています。

https://bugzilla.mozilla.org/show_bug.cgi?id=1617609

Safari での SameSite 属性が None である Cookie の扱い

一方 Safari は、2020 年 3 月に 3rd Party Cookie を完全にブロックするとアナウンスしています。

https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/

3rd Party Cookieとは、cross-site なリクエストに対する Cookie を指します。

この挙動は SameSite 属性に None を指定した時の挙動と矛盾するため、Safari だとどうなるのだろうと思い調べてみたのが今回のきっかけです。

Safari 13.0 及び 13.1 で動作確認しましたが、3rd Party Cookie をブロックするケースとしないケースがあることがわかりました。 さらに挙動を調べてみたところ、Website tracking の設定である Prevent cross-site tracking の設定によって挙動が変わることがわかりました。

f:id:cybozuinsideout:20200430175409p:plain
SafariのWebsite Trackingの設定

この設定が有効になっている場合、SameSite 属性に None を指定しても 3rd Party Cookie は付与されません。 この変更がいつから適用されているのかは不明ですが、現在ではこの設定がデフォルトで有効になっているため、Safari ではデフォルトで 3rd Party Cookie が付与されない状態になっています。

ただし、Storage Access API を利用することで 3rd Party Cookie を利用可能にする方法が用意されています。

https://webkit.org/blog/8124/introducing-storage-access-api/

SameSite 属性を DevTools で確認する

今回この検証を行っている際、SameSite 属性が None の場合の各ブラウザの DevTools での表示が異なっていることがわかりました。 下記は、それぞれのブラウザ毎に取得したスクリーンショットです。

  • Chrome

    f:id:cybozuinsideout:20200430175439p:plain
    Chrome 81でのCookieの表示

  • Firefox

    f:id:cybozuinsideout:20200430175501p:plain
    Firefox 75でのCookieの表示

  • Safari

    f:id:cybozuinsideout:20200430175516p:plain
    Safari 13.1でのCookieの表示

Chrome は未指定と None が区別されています。したがって、現状だとデフォルト値が None なのか Lax なのかを理解する必要がありそうです。 Firefox はデフォルト値も含めて全て None と表示されています。 Safari は None の表示は — で表示されます。バグかと思い確認してみましたが意図した挙動のようです。

参考:

まとめ

今回は、Cookie に新しく追加された SameSite 属性について調べた内容を共有しました。

このようにブラウザの変更をキャッチアップして、プロダクト開発チームにフィードバックするのもフロントエンドエキスパートチームの仕事です。 サイボウズでは、ブラウザの更新情報をチェックするのが趣味というエンジニアを募集しています。

https://cybozu.co.jp/company/job/recruitment/list/front_end_expert.html