Sharing Sessions Between Rails 2 and Rails 3 Applications

August 4, 2010
rails3 sessions rails2

I have been working on writing new applications in Rails 3 at work, but up until this week, they weren't at a point where I would actually interact with my existing applications since they were just in development. However, this week, I was at a point where I could start working on the integration.

The main thing that needs to happen between applications is I have a central authentication/authorization application that I share the session secret key and the user database with my other applications to serve as a sort-of single sign-on set up. It has worked well enough to this point, but I had always been running applications at approximately the same version of Rails 2 on all of the applications.

The first step is to configure the applications to use the same domain and secret key.

On my rails2 app, I had a config like in config/initializers/session_store.rb:

ActionController::Base.session = {
  :key         => '_sso_session',
  :secret      => 'a really long hex string'
  }


And then in config/environments/development.rb

config.action_controller.session = { 
  :domain => ".rails.local" 
}


Originally in my Rails 3 app, I had something in the config/initializer/session_store.rb like this:

Rails.application.config.session_store :cookie_store, {
  :domain      => '.rails.local',
  :key         => '_sso_session',
  :secret      => 'the same really long hex string'
}


But, I found that it just wasn't taking the session at all. After much combing through the Rails 2 and 3 source to see why, I finally found this in the Changelog:

*Rails 3.0.0 [beta 3] (April 13th, 2010)*

* Renamed config.cookie_secret to config.secret_token and pass it as env key. [JV]


*Rails 3.0.0 [beta 2] (April 1st, 2010)*

* Session store configuration has changed [YK & CL]
  config.session_store :cookie_store, {:key => "..."}
  config.cookie_secret = "fdsfhisdghfidugnfdlg"

OK, that was a pretty quiet, but major change.. and it only caused me a few hours of grief. But, I made those changes..

Rails.application.config.session_store :cookie_store, {
  :domain      => '.rails.local',
  :key         => '_sso_session'
}

Rails.application.config.secret_token = 'the same really long hex string'


And in the RC for Rails 3, they have moved the secret token into its own initializer at config/initializers/secret_token.rb. Since I created the application using beta4, I didn't see this.

First issue fixed. When I got that I was able to see the session being passed, but now ran into a new problem from the Rails 2 app.

I got the very useful error message:

ActionController::SessionRestoreError in User sessionsController#new

Session contains objects whose class definition isn\'t available.
Remember to require the classes for all objects kept in the session.
(Original exception: #{const_error.message} [#{const_error.class}])

Some more time spent with irb and I found that it was passing the Rails 3 flash class of ActionDispatch::Flash::FlashHash and Rails 2 didn't know about that since it uses ActionController::Flash::FlashHash, and abstract_store.rb has code to check to make sure that a class that is set in the session is a known, and since the classes are different for flash messages bewteen Rails 2 and Rails 3, this alert was generated.

OK, rather than monkey patching Rails 2 to know about ActionDispatch, I just decided to go the easier route and just not set the flash message. I did get a similar problem with my Rails 2 application setting the flash and getting a similar (but fixed) error message about not having ActionController::Flash::FlashHash, but easily enough fixed by just removing the flash messages.

Ultimately, the solution is going to be to get everything upgraded to Rails 3, but hopefully someone who is going through similar pains will find this useful since the solutions aren't always obvious with error messages and stack traces.

Update: Another solution instead of just removing flash messages, is to use flash.now, which shouldn't put the flash messages in the session.