Sunday 10 May 2009

cookies and hosts / domains

I have been struggling for weeks with a problem of users being logged in to mysite.com, but not en.mysite.com and es.mysite.com. I posted on Ruby Groups and even tried to hire someone to do the work... but to no avail.
Finally I think I cracked it today.

Two things. First, for some reason doing this didn't work:
  if RAILS_ENV == 'production'
config.action_controller.session = {
:session_key => '_my_session',
:session_domain => '.mysite.com',
:secret => 'xxx'
}
else
config.action_controller.session = {
:session_key => '_my_session',
:session_domain => '.mysite.local',
:secret => 'xxy'
}
end


So, I substituted this into each environment file:
config.after_initialize do
ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:session_domain] = '.mysite.local'
end


That got my session's having the correct domain set (.mysite.com) meaning that the session was saved across subdomains.

Cookies

But then I encountered a second problem. Cookies.
After switching to hide and seek / show and tell methods to enable me to page cache even pages that had logged in status all over them (more on this in another post) I needed some user info in a cookie. But my cookies were tied to the subdomain!
I was setting the cookies like this:

      cookies[:current_user] = {
:cart_items_count => cart_items_count,
:nothing => 1
}.to_json


I thought, ok I just need to add the domain in:
      cookies[:current_user] = {
:cart_items_count => cart_items_count,
:nothing => 1,
:domain => ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:session_domain]
}.to_json


No...this didn't work. Everything was being chucked into the cookies 'value' and not the domain field (same happened if I added in an expires_at key). What was going on?
Aha! It is the json-izing.

So, I moved that out to a seperate variable:
      value = {:cart_items_count => cart_items_count, :nothing => 1}.to_json
cookies.delete :login, :domain => ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:session_domain]
cookies[:current_user] = {
:value => value,
:domain => ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:session_domain]
}


Now my cookies had the proper domain info and the value was still proper json. And now my users are logged in across sub domains!

No comments: