結論
SameSite=None; Secure
にしているサービスは開発環境もHTTPS化しておきましょうというお話です。Chromeは84よりデフォルトの挙動が変わり、FirefoxもFirefox 69からSameSite属性が利用できるようになっています(デフォルトの挙動はまだのよう)。
自分の担当しているサービスでもメンバーが既にHTTPS化してくれていましたが、HTTPとHTTPS両方使える状態だったので今回の事象に遭遇してしまいました。
経緯
初回リクエスト時のレスポンスを返す際に生成したCSRFトークンがsession[:_csrf_token]
に格納され、次のリクエスト時には当該データとリクエスト時に受け取ったCSRFトークンを突き合わせリクエストの整合性を担保している。
具体的にはこのあたり。
def real_csrf_token(session) # :doc: session[:_csrf_token] ||= SecureRandom.base64(AUTHENTICITY_TOKEN_LENGTH) Base64.strict_decode64(session[:_csrf_token]) end
出典: actionpack/lib/action_controller/metal/request_forgery_protection.rb
しかし2回目のリクエスト時にはその前に生成されているはずのCSRFトークンがsession[:_csrf_token]
に格納されておらず、不正なリクエストと判定されているようだった。Safariで確認したところ想定通りのタイミングでsession[:_csrf_token]
に値が格納されていた。
自分で挙動を調査しチームメンバーにヒアリングしたところ
という状態だった。
HTTPSでログイン可能という挙動とデバッグの過程から、SameSite Cookiesの機能ではないかと疑った。 Chromeでログインできるメンバーに確認したところその人だけバージョン63のChromeを使っており、ログインできない組は64を使用していた。確認したところ、新型コロナウィルスの影響で延期されていたSameSite cookieの対応が7/14 バージョン84から再開されており、その影響であることが判明した。
参考