🍪

RailsのセッションCookieが「session_id」から切り替わらなかった理由と対処法

に公開

_swipe_app_session が付かなかった事件

Rails 8 + API モードのプロジェクトで、config/initializers/session_store.rb

Rails.application.config.session_store :cookie_store,
  key: "_swipe_app_session",
  secure: true,
  httponly: true

のようなカスタム設定を書いたのに、ブラウザにはいつまで経っても _session_id が届いてしまう――そんな現象に遭遇しました。設定を何度見直しても正しそうなのに、結果が変わらない。原因は「ミドルウェアを差し込むタイミング」にありました。

初期化の順番とサンプルコードで俯瞰

まずは「普通に書くとどうなるか」を簡単な例で追いかけてみましょう。

# config/application.rb
module DemoApp
	class Application < Rails::Application
		config.load_defaults 8.0
		config.api_only = true

		config.middleware.use ActionDispatch::Cookies
		config.middleware.use ActionDispatch::Session::CookieStore, config.session_options
	end
end

# config/initializers/session_store.rb
Rails.application.config.session_store :cookie_store, key: "key_name"

どちらも素直に見えますが、実際には次の順番で処理されています。

  1. application.rb がクラス定義として評価される
    config.middleware.use ...その場で実行され、CookieStore が「デフォルト設定」のまま登録される。
  2. Rails.application.initialize! が呼ばれ、初期化フェーズに突入する。
  3. そこでようやく config/initializers/session_store.rb が実行され、config.session_store(= config.session_options)が書き換わる。

しかし肝心のミドルウェアは すでに登録済み。あとから変更された config.session_options は既にスタックに積まれている CookieStore には反映されません。そのためブラウザには旧来の _session_id が飛び続ける、というわけです。

解決策と「初期化」+「ミドルウェア」の理解

どう直したか

ミドルウェアを挿し込むタイミングを「初期化が完了した後」にずらして、改めて登録し直します。

# config/application.rb
module SwipeApp
	class Application < Rails::Application
		config.load_defaults 8.0
		config.api_only = true

		config.middleware.use ActionDispatch::Cookies

		initializer "session_store.configure" do |app|
			app.middleware.use ActionDispatch::Session::CookieStore, app.config.session_options
		end
	end
end

initializer ブロックは config/initializers/*.rb と同じタイミングで実行されるため、その時点では session_store.rb による設定が app.config.session_options に入っています。これを渡してから CookieStore を登録すれば、_swipe_app_session というキー名を含め、意図した Secure/SameSite/Domain の設定も丸ごと反映されます。

初期化とは?ミドルウェアとは?

  • 初期化 … アプリがリクエストを受け付ける前に一度だけ行うセットアップ。Rails では config/application.rbconfig/environments/*.rbconfig/initializers/*.rb の順で読み込まれます。
  • Rack ミドルウェア … リクエスト・レスポンスを通過させながら処理を差し込む仕組み。ActionDispatch::CookiesActionDispatch::Session::CookieStore などがここに属します。

今回の問題は「クラス定義の段階(初期化より前)でミドルウェアが登録されてしまった」こと。つまり設定ファイルは正しかったのに、適用するタイミングがズレていただけだったのです。

まとめ

  • _swipe_app_session が付かなかったのは、CookieStore を 初期化前に 登録していたせいで config.session_options が空のまま渡っていたから。
  • initializer ブロックでミドルウェアを差し込むように変更すると、session_store.rb の設定が反映された状態で _swipe_app_session が発行される。
  • Rack ミドルウェアは「登録した時点のオプション」で固定されるため、設定を後から変える場合は登録タイミングも意識する。

Rails の初期化については、サーバー起動してくれるまでにどのようなファイルがどんな順序で実行されるのかを知ることで、起動できないといったエラーや今回の僕のような標準設定が意図しない形で使用されてしまうというミスを防ぐことができると思いますので覚えておくといいのかなと思いました。

Discussion