Session expiry in Rails
Something that stumped me for quite a few days was the fact that I couldn’t log into my application after some times. It was truly irritating because after migrating to Mongrel and having 3 Mongrel clusters running on an Apache it was blazing fast but I couldn’t log in after some time!
Checking the error logs I found this seems to be the problem.
Filter chain halted as [login_required] returned false
What's this then? After more research I suspected that the reason why my login throws me out is because the session is no longer valid. Following this clue, I installed LiveHTTPHeaders, a Firefox plug-in that snoops the HTTP headers that are transferred to and from the browser. This gave me more information but raised some very puzzling questions:
HTTP/1.x 200 OK Date: Fri, 15 Sep 2006 02:11:59 GMT Status: 200 OK Cache-Control: no-cache Content-Type: text/html; charset=UTF-8 Set-Cookie: sam_production_session_id=bdbae24176c4bfbec1be1109c2beee8c; path=/; expires=Thu, 14 Sep 2006 17:25:22 GMT Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 667 Connection: close
Apparently the session cookie that was set was expired as I was trying to log in! Of course the session was invalid and I was logged out! Curiouser and curiouser.
What was happening? Running this on Webrick works perfectly so I was really stumped. What was wrong with Apache/Mongrel that this doesn't work? Then I remembered that I set the expiry of the session to 1 hour in my application.rb
class ApplicationController 1.hour.from_now end
I tried to login repeatedly and looked at the LiveHTTPHeaders again. Surprise! The cookie expiry date doesn't change! So what's wrong?
Well after more research, apparently the main problem is because I was running Webrick on a development environment while my Apache/Mongrel was running on production. In development mode, ApplicationController reloads every time a request is made and session is called for each request. In a production environment, session is only called once and therefore the expiry is effectively fixed. The reason why I could log in initially was because during my setup I restarted the cluster repeatedly.
My solution? I removed session expiry, such that the session doesn't expire. This means that as long as I don't log out or close the browser, the session remains valid. So what are the other options? Unfortunately as I found out, Rails doesn't really allow any easy means of doing dynamic session expiry. This entry in the rubyonrails wiki provides good information on the possible alternatives. Another alternative is suggested by Coda Hale in his blog.
If you have anything drop me a note as well.