Issues with sessions when using `redis_store` and custom session key names
lavilet opened this issue · comments
Describe the bug
Hey guys 👋 . Recently we've migrated from using ActiveRecord Session Store (https://github.com/rails/activerecord-session_store) to redis_store (https://github.com/redis-store/redis-actionpack). After this change our Sail Dashboard stopped working:
When debugging from within Sails:
[1] pry(#<Sail::SettingsController>)> session.options
=> #<ActionDispatch::Request::Session::Options:0x00007fa5b36098b0
@by=
#<ActionDispatch::Session::RedisStore:0x00007fa593577a48
@app=#<ActionDispatch::Routing::RouteSet:0x00007fa571addf18>,
@conn=
#<Redis::Rack::Connection:0x00007fa5935771b0
@options=
{:path=>"/", :domain=>nil, :expire_after=>nil, :secure=>false, :httponly=>true, :defer=>false, :renew=>false, :redis_server=>nil},
@pool=nil,
@pooled=false,
@store=#<Redis client v4.6.0 for redis://0.0.0.0:6379/0>>,
@cookie_only=true,
@default_options=
{:path=>"/", :domain=>nil, :expire_after=>nil, :secure=>false, :httponly=>true, :defer=>false, :renew=>false, :redis_server=>nil},
@key="_session_id",
@mutex=#<Thread::Mutex:0x00007fa5935771d8>,
@same_site=nil>,
@delegate=
{:path=>"/", :domain=>nil, :expire_after=>nil, :secure=>false, :httponly=>true, :defer=>false, :renew=>false, :redis_server=>nil}>
What I've noticed - the session key ("_session_id") looks like kind of a default key - in our configuration we are using different key name, so when we would try to fetch sesssion.id we'll get nil, because parent app stores session under different key.
When I've updated this line
Line 42 in 7da7c74
if Rails.application.config.session_store.nil?
config.middleware.use ActionDispatch::Session::CookieStore
end
Everything works as expected - dashboard loads, and when debugging and checking whats inside session object:
=> #<ActionDispatch::Request::Session::Options:0x00007fb952e3a720
@by=
#<ActionDispatch::Session::RedisStore:0x00007fb9e2a5fa98
@app=
#<ActionDispatch::ContentSecurityPolicy::Middleware:0x00007fb9e2a5fcc8
@app=
#<Rack::Head:0x00007fb9e2a5fed0
@app=
#<Rack::ConditionalGet:0x00007fb9e2a5ff48
@app=
#<Rack::ETag:0x00007fb9e2a54008
@app=
#<Rack::TempfileReaper:0x00007fb9e2a54058
@app=
#<Warden::Manager:0x00007fb9e2a54170
@app=
#<ApolloUploadServer::Middleware:0x00007fb9e2a541c0
@app=
#<Warden::JWTAuth::Middleware:0x00007fb9e2a54210
@app=#<Bullet::Rack:0x00007fb9e2a54260 @app=#<ActionDispatch::Routing::RouteSet:0x00007fb984297210>>>>,
@config=
{:default_scope=>:account,
:scope_defaults=>{},
:default_strategies=>
{:account=>[:jwt, :database_authenticatable],
...},
:intercept_401=>false,
:failure_app=>#<Devise::Delegator:0x00007fb98468e3f0>}>>,
@cache_control="max-age=0, private, must-revalidate",
@no_cache_control="no-cache">>>>,
@conn=
#<Redis::Rack::Connection:0x00007fb9e2a5f368
@options=
{:path=>"/",
:domain=>nil,
:expire_after=>1 minute,
:secure=>false,
:httponly=>true,
:defer=>false,
:renew=>false,
:redis_server=>["redis://0.0.0.0:6379/0/session"],
:servers=>["redis://0.0.0.0:6379/0/session"],
:threadsafe=>true},
@pool=nil,
@pooled=false,
@store=#<Redis client v4.6.0 for redis://0.0.0.0:6379/0>>,
@cookie_only=true,
@default_options=
{:path=>"/",
:domain=>nil,
:expire_after=>1 minute,
:secure=>false,
:httponly=>true,
:defer=>false,
:renew=>false,
:redis_server=>["redis://0.0.0.0:6379/0/session"],
:servers=>["redis://0.0.0.0:6379/0/session"],
:threadsafe=>true},
@key="_hub_session",
@mutex=#<Thread::Mutex:0x00007fb9e2a5f390>,
@same_site=nil>,
@delegate=
{:path=>"/",
:domain=>nil,
:expire_after=>1 minute,
:secure=>false,
:httponly=>true,
:defer=>false,
:renew=>false,
:redis_server=>["redis://0.0.0.0:6379/0/session"],
:servers=>["redis://0.0.0.0:6379/0/session"],
:threadsafe=>true,
:id=>"7f9d96ee441b7b418f5f2573263fa03c"}>
[7] pry(#<Sail::SettingsController>)>
So here I can see way more details and options, also the key matches the one we've configured ("_hub_session"). Looks like when we are adding a middleware in after_initialize block it somehow overrides some of the configs from the base/parent app 🤔 .
Environment
Gemfile
source 'https://rubygems.org'
ruby '2.7.6'
gem 'rails', '~> 6.0.0'
gem 'redis-actionpack'
gem 'sail'
...
To Reproduce
Steps to reproduce the behavior:
Install 'redis-actionpack' gem,
create app/initializers/session_store.rb
opts = {
key: '_hub_session',
servers: ['redis_url'],
expire_after: 1.hour,
threadsafe: true,
secure: !(Rails.env.development? || Rails.env.test?)
}
Rails.application.config.session_store :redis_store, opts
routes:
...
authenticate :user, ->(u) { u.admin? } do
mount Sail::Engine => '/sail'
...
Login and visit localhost:3000/sail
Expected behavior
User should see a Sail Dashboard
Actual behavior
User sees an error page.