May 7

Rails Gotcha #9: Disabled Sessions

by Peter Jones / May 7, 2008

I was recently working on a Rails application where sessions were disabled in the application controller (affecting all other controllers), and needed to be turned back on in certain other controllers. Basically, sessions were only needed on the admin controllers.

While testing this application I ran into a few surprises, leading to this 2 in 1 Rails Gotcha, and two patches to Rails edge.

Turning Sessions Back On

As you know, turning off all sessions is simply the matter of using a class method in your ApplicationController:

session(:off)

Intuitively you would think you could turn the session back on in one of your other controllers using the opposite:

session(:on)

This doesn't work, however. It also doesn't raise any exception or produce any warning whatsoever. As a matter of fact, if you look at the source code, using :on has the exact same effect as using :off.

The correct way to enable sessions after they have been turned off is to pass a hash with the key :disabled with the value false:

session(:disabled => false)

If you're like me, and you'd like to see the session(:on) trick work, please go vote a +1 for my ticket.

Sessions and Forgery Protection

Turning sessions off in the application controller has an interesting side effect if you also have forgery protection enabled:

protect_from_forgery(:secret => 'foobar')
session(:off)

In order for the forgery protection to work, you need to have sessions enabled (it probably doesn't even make sense to guard against forgery if you don't have them enabled). So, if you have sessions disabled, forgery protection enabled, and post a form, you get this helpful error message:

undefined method `session_id' for {}:Hash

This is the result of some checks in the forgery code for a valid session happening too late. I've created a patch that moves the session checking to the correct location, producing this error message instead:

InvalidAuthenticityToken: "Request Forgery Protection requires a valid session.  Use #allow_forgery_protection to disable it, or use a valid session."

Without the patch, however, the workaround is simple, either turn off forgery protection when you turn off sessions, or use something like the following in your application controller:

prepend_before_filter do |controller|
  controller.class.allow_forgery_protection = controller.session_enabled?
end

Don't Forget to Vote

Please vote a +1 for the following patches:

Updates

Sunday, May 11, 2008: Both of these patches have been accepted into Rails, and the tickets were closed. Thanks for the votes!


Tags: rails bug gotcha

0 Comments