マージ時に、CSRFのトークンのエラーが出たのでメモしておきます。
RailsのCSRFトークンの仕組みは、ページに埋め込んだトークン(パラメータ)とCookie(デフォルトの場合)のセッション内(_アプリ名_sessionに複数項目を暗号化して保持)に入れたトークンが一致するかで判定しています。
何らかの理由で、Cookieが保存できないとセッションが取得できない為、このエラーになります。(今回のケースはこれ)
他には、JSON等でパラメータにトークンをセットしてない場合も起こりますが、それはまた別の機会に。
エラー画面およびログ
入力項目(今回は、メールアドレスとパスワード)のバリデーションやチェック前に動くので、今回は空のままログインを押しています。
rails sのログ
Started POST "/users/sign_in" for 127.0.0.1 at 2020-08-25 22:38:04 +0900 Processing by Users::SessionsController#create as HTML Parameters: {"authenticity_token"=>"evfOzNKwNIWrozSimS75ohh1L+0McGgPOVkaDvaPWtVAnsP8mcxpNdHCUru7lXn6FB4bfLluQ/MFV1gT4UFdCw==", "user"=>{"email"=>"", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"ログイン"} Can't verify CSRF token authenticity. Completed 422 Unprocessable Entity in 2ms (ActiveRecord: 0.0ms | Allocations: 1352) ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
ディベロッパーツールで確認
Chromeのディベロッパーツールで、Cookieがセットされていないと判明。
実装確認
このブランチでは、サブドメイン間でセッションを共有(ログイン状態を維持)する為、ドメインを明示的に指定しています。
config/application.rb
config.session_store :cookie_store, domain: Settings['base_domain']
config/settings/development.yml
base_domain: 'localhost.local:3000'
元のブランチで、ドメインとポートを共通化させた為、[localhost.local]だったが[localhost.local:3000]に変わってしまいました。
ポートが入っているとCookieが保存されない事が解りました。
本番ではポート指定しないので、開発環境のみの問題ですね。
実装修正
これだけの為に、文字列を加工するのも無駄なので、定数を追加して対応しました。
config/application.rb
- config.session_store :cookie_store, domain: Settings['base_domain'] + config.session_store :cookie_store, domain: Settings['cookie_domain']
config/settings/development.yml
+cookie_domain: 'localhost.local' base_domain: 'localhost.local:3000'
※test.ymlやproduction.ymlも定義(若干、冗長ですがシンプルで解りやすい)
【参考】ここまでのコミット内容
https://dev.azure.com/nightonly/rails-app-origin/_git/rails-app-origin/commit/b3729dee99eaf34557623607a8481eb2931d7ae7
“ActionController::InvalidAuthenticityTokenの解消(解決済み)” に対して1件のコメントがあります。