How to dynamically change the session cookie name in Rails?
Asked Answered
F

0

6

I have a Ruby on Rails 4.2 multi-tenant application where I want each tenant to use it's own session cookie and cookie options. I tried different approaches but I can't get every detail right.

To add more context, tenant is selected from the host url in the request, in a Middleware, and set to a thread variable I can access down the stack. Let's call that settings object as Settings.current_account.

Option 1: middleware:

class AccountableSessionCookies
  def initialize(app)
    @app = app
  end

  # @param [Hash] The Rack environment.
  def call(env)
    dup.call!(env)
  end

  # @param env [Hash] The Rack environment.
  def call!(env)
    env['rack.session.options'][:key] = Settings.current_account.session_key
    env['rack.session.options'][:expire_after] = Settings.current_account.session_expiration
    @app.call(env)
  end
end

and then in an initializer

Rails.application.config.session_store :cookie_store, key: 'bla',
                                                      expire_after: 1_209_600

Result: this will allow me to set expire_after, but not the cookie name, that will remain bla.

Option 2: custom cookie store

module ActionDispatch
  module Session
    class AccountCookieStore < CookieStore
      def initialize(app, options={})
        super(app, options.merge!(key: Settings.current_account.session_key),
                                  expire_after: Settings.current_account.session_expiration)))
      end
    end
  end
end

and then in an initializer:

Rails.application.config.session_store :account_cookie_store, key: 'bla',
                                                              expire_after: 1_209_600

But then it seems like the AccountCookieStore instance is loaded BEFORE the call gets to the middleware were Settings.current_account, hence no values can be fetched from the request and used to create the cookie.

Option 3: after_filter in ApplicationController

  after_filter :short_session

  def short_session
    request.session_options = request.session_options.dup
    request.session_options[:expire_after] = 100.days.to_i
    request.session_options[:key] = 'mynewkey'
    request.session_options.freeze
  end

This just does not work.

What am I missing? Any ideas on how can I get this done?

Forecourse answered 18/9, 2018 at 18:14 Comment(1)
FWIW at least same_site supports getting a proc -- :same_site => proc { |request| :lax }Feminize

© 2022 - 2024 — McMap. All rights reserved.