Railsでcookieを使用するときのやり方について、少し知見が溜まったのでアウトプットしていきたいと思います。
※ RailsをAPIサーバーとして使うことを前提としています。
APIモードでクッキーを使う設定
Rails APIモードの場合は、デフォルトではCookieを使用するミドルウェアが無効になっているので、有効にしておきます。
class Application < Rails::Application
# 略
config.middleware.use ActionDispatch::Cookies
end
class ApplicationController < ActionController::API
include ActionController::Cookies
# 略
end
これでcookiesメソッドが使えるようになっているはずです。
APIとして使うことが前提なので、ブラウザにCORSで弾かれないようにAccess-Control-Allow-Origin
ヘッダにオリジンが指定されていること(「*」ではだめです。)とAccess-Control-Allow-Credentials: true
がレスポンスに含まれていることをチェックします。
SameSite属性とSecure属性が必須!
最近のモダンブラウザでは、SameSite属性値のデフォルトがLaxになりました。
これにより、クロスサイトに該当するサーバーにはcookieが送信されなくなりました。つまり、SPA構成でブラウザのCookieに値を保存するにはSameSite属性をnoneに設定する必要があります。具体的には下のようにします。
※ ここではすべてのCookieでnoneを設定する想定でミドルウェアに設定しています。
config.action_dispatch.cookies_same_site_protection = :none
また、SameSite属性がnoneの場合は、CookieのSecure属性がtrueの場合にしか、Cookieを送信しません。具体的にはこのように設定します。
cookies[:user_id] = {
value: token,
expires: Time.current + 1.day,
path: '/',
httponly: true,
secure: true # 必須
}
※ Secure属性はHTTPSで暗号化された通信のときのみCookieを送信するという設定です。https://developer.mozilla.org/ja/docs/Web/HTTP/Cookies#cookie_%E3%81%B8%E3%81%AE%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E5%88%B6%E9%99%90
※ Chrome80から変更されたCookieに関する仕様変更の記事
https://www.docusign.jp/blog/google-chrome-80-samesite-cookie
HttpOnly属性はできるだけつける
サーバー側のセッションを持続させるクッキーなどJavaScriptから操作する必要のないクッキーに対してはHttpOnly属性をつけておくのがよいです。これにより、XSSによる攻撃を防ぐのに役立ちます。
cookies[:user_id] = {
value: token,
expires: Time.current + 1.day,
path: '/',
httponly: true, # JavaScriptから利用しない場合はつける
secure: true
}
※ HttpOnly属性がtrueになっていると、JavaScriptからdocument.cookie
で値を取得できなくなります。
その他の属性
ミドルウェアが勝手につけてくれるので意識する必要はないですが、Domain属性やPath属性も必須で必要になるので、Rails以外でCookieを扱うときは注意が必要です。管理人はGolangのEchoを使っているときにPath属性を指定し忘れハマった記憶があります・・
クッキーの削除するときの注意
cookieを削除するときはdeleteメソッドを使うのですが、少々なぞな挙動をすることが多いので気をつけます。Secure属性やPath属性を指定しないと削除できないことがあったので、必ず動作確認をしてきちんとクッキーが削除されているのかを確認するということをやったほうがいいと感じました。
さいごに
ここまで読んでいただきありがとうございました。
分かりにくいやアドバイス等ありましたらコメントくださると幸いです。では!
Twitterもやってますので、フォローしていただけるとうれしいです。↓