helion-prime
home about us blogs contacts

Multi-domain applications in Ruby on Rails

Published by alex.shapovalov on September 3, 2009 under internet, ruby, web-development  

preamble

Ruby on Rails is a great framework that still luck some common features, among them: multi-domain support.
Here I will describe fast solution that doesn’t work for every browser and another one that do the work.

Ok, you did your homework and google something like ‘ruby on rails multi-domain’.
Very often provided solution:

edit environment.rb

1
config.action_controller.session = {:domain => '.mydomain.com'}

With that parameter Rails always read cookies from same domain. In real some browsers forbid for applications to read cookies from other domain due to insecurity of that operation. And as Mozilla Firefox in set of browsers that forbid that we just need another solution.

Now it’s clear that we should implement necessary functionality other way.

Here we go:

1. will store session ID in the database(by default Rails2 store it in cookies)

environment.rb:

1
config.action_controller.session_store = :active_record_store

and then execute rake task that create necessary DB migration:

1
rake db:sessions:create

Apply it with: rake db:migrate.

2. setup session parameters

environment.rb:

1
2
3
4
5
6
7
8
9
require "rubygems"
require "active_support"

config.action_controller.session = {
   :session_key => '_myapp_session_id',    # session identification key
   :secret      => '89sHslddfsd98klasdKd', # hash code of session generator(make it random and longer)
   :cookie_only => false,
   :expire_after => 1.week,                # TTL (time to live)
}

3. let’s create session creation handler

application_controller.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
before_filter { |controller|
   opts = controller.request.session_options
   key = opts[:key]

   # use session ID if it's passed
   if controller.params[key]       
      # session initialization with old ID
      controller.session[:nothing]

      opts[:id] = controller.params[key]
      controller.request.session_options = opts
     
      # session initialization with new ID
      controller.session[:nothing]
   end
}

4. session pass

We need to pass session ID as parameter when user change domain name, and within domain we still use cookie.

1
“#{request.session_options[:key]}” => request.session_options[:id]

It’s wise to use session initialization before request.session_options[:id] invocation due to Rails use lazy loading, and session can be uninitialized.
Use something like: session[:nothing].

Pay attention that information that Rails get from cookie has bigger priority, and so if you have some parameter in cookie Rails will use it firstly.

Note:
An attacker can still steal you session ID by sniffing the network, or exploiting javascript, he/she gets the value from the cookie itself. If you care about security so much just use HTTPS.

Be Sociable, Share!

4 Responses to “Multi-domain applications in Ruby on Rails”

  1. Fima says:

    Thanks for the interesting post. Do you have a site using this today you can point us to? I’m interested in building a site very similar to WPMU – but with Rails.

  2. alex.shapovalov says:

    At this time the application that use this functionality is in development phase,
    but it should be ready at begging of November, and I’ll be glad to provide you with their URL then.

    So, see you soon!

  3. Fima says:

    Definitely hit me up! Thanks Alex.

  4. alex.shapovalov says:

    Hello Fima.

    Sorry for some delay, but finally we’ve launched the application:
    http://myvillage.com .. welcome!

Leave a Reply

©2010 Helion-Prime Solutions Ltd.
Custom Software Development Agile Company.