Open jebentier opened 3 years ago
This is still an issue in rails=6.1.3.2
and activerecord-session_store=2.0.0
.
Thank you @jebentier for the workaround solution For those who use Apartment gem you might want to add below line of code
---
def get_session_model(request, id)
Apartment::Tenant.switch! request.subdomain #gem 'apartment', '~> 2.2'
---
Thank you @jebentier for the workaround solution For those who use Apartment gem you might want to add below line of code
--- def get_session_model(request, id) Apartment::Tenant.switch! request.subdomain #gem 'apartment', '~> 2.2' ---
this issue is from middlewares order
run rake middleware
to see middlewares order
use ActiveRecord::Migration::CheckPending
use ActionDispatch::Cookies
use ActionDispatch::Session::ActiveRecordStore
use ActionDispatch::Flash
use ActionDispatch::ContentSecurityPolicy::Middleware
use ActionDispatch::PermissionsPolicy::Middleware
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
use Rack::TempfileReaper
use ActiveRecord::Middleware::ShardSelector
in my case is ShardSelector
behind ActiveRecordStore
if you're using Apartment
find apartment middleware that handles switch database
add this line to application.rb
and see the magic :D
config.middleware.move_before ActionDispatch::Session::ActiveRecordStore, ActiveRecord::Middleware::ShardSelector
I've been working on upgrading the platform at my company from Rails 4.2 to Rails 5.x over the past couple months and ran into a rather interesting issue that I've seen referenced symptomatically a few different places. The most prevalent of the symptoms is around the usage of
activerecord-session_store
and CSRF tokens. Forms that are using CSRF protection on a user with no pre-existing session, are always coming back asinvalid
because the session store is losing track of the CSRF token stored in the session.The issue stems from a difference in functionality between the implementations of
get_session_model
in legacy_support.rb and active_record_store.rb. When encountering a session that has not been stored yet, theLegacySupport
implementation creates the session with the ID that was passed, while theActiveRecordStore
implementation generates a fresh session ID and persists that one. The latter introduces a bug when used withrack
, because when invoking commit_session,rack
makes the assumption that the data that is returned bywrite_session
is what should be persisted as the value of the cookie. And what is returned byActiveRecord::SessionStore#write_session
is the session id that was passed to it.In the Rails 5 section below, you'll see that the session ID persisted to the store is not the same as the ID set in the cookie.
Proof of Bug
config/application.rb
Rails 4.2 HTTP Response
Of note is the session ID and the CSRF token:
Prying into the form submission shows:
Rails 5.2 HTTP Response
Of note is the session ID and the CSRF token:
Prying into the form submission shows that the session ID set in the cookie doesn't exist:
In the logs I found that a different session ID was saved to the session store:
In the same
pry
from above, proof that the session saved to the store is valid:Workaround
By applying the following patch to
ActiveRecordStore#get_session_model
I was able to resolve this issue and carry on with the upgrade.I would be more than happy to discuss and work with anyone to implement a permanent fix to this.