3
votes

I need to switch the session store in my Rails 3 app from cookie_store to redis-session-store. There are many reasons for this (security, SSO with other Rails and non-Rails apps). Are there any best practices on how to do it without loosing all current sessions?

What i could imagine is a two steps approach:

  1. Collect all user sessions for N days and store them in the DB or in Redis (update if already stored).
  2. Use stored user sessions to create entries in Redis.

Alternatively, on the fly migration would also be possible. Means read cookies, use secret key to decrypt the session data and store it as a new session in Redis.

2

2 Answers

0
votes

I realize this ticket is pretty old, but this may help others. We ended up changing our session store to Redis, but then still looking for the legacy cookie (for a week or two) before no longer respecting them.

There are probably some security concerns to consider before using this strategy - you want to make sure those risks are worth it compared to the cost of having to sign your entire user-base out all at once. With Rails, the cookies are encrypted and can't be tampered with.

Here's what we used:

class SessionsController < Devise::SessionsController
  LEGACY_COOKIE_NAME = "_old_session_name".freeze

  def new
    return if detect_valid_cookie

    super
  end

  private

  def detect_valid_legacy_cookie
    legacy_cookie = request.cookie_jar.encrypted[LEGACY_COOKIE_NAME].presence || {}
    valid_user_id = legacy_cookie['warden.user.user.key'].try(:first).try(:first)
    return unless valid_user_id

    user = User.find_by(:id => valid_user_id)
    return unless user

    if sign_in user
      request.cookie_jar.delete(LEGACY_COOKIE_NAME)
      redirect_to root_path # or whever you want
      true
    else
      false
    end
  end
end
-2
votes

Stolen from here:

http://www.happybearsoftware.com/almost-protect-yourself-from-cookie-session-store.html (the last two sections)

Basically, use this:

Rails.application.config.action_dispatch.cookies_serializer = :hybrid

Quote follows:

This will cause Rails to accept sessions serialized with Marshal and exchange them for sessions serialized with JSON.

After you're confident that all your users sessions have been converted to JSON, you can roll out another release that flips the config value to :json.

Note: If you're storing complex Ruby objects in the session and need them to be serialized with Marshal, you won't be able to use the JSON serializer.