Rails, Authlogic and Single Sign On

This post is for Rails 2. For Rails 3 compliant code, see the first comment.

Introduction

We have a suite of integrated tools and we needed a single sign on solution. We looked at OpenID, OpenAuth and CAS but decided to roll our own so that we could manage all our user accounts, sessions, roles and permissions centrally. We are also behind a secure network (Active Directory) and the use of OpenID and OpenAuth was ruled out anyway…

What did we need?

1. A central app to manage user authentication and sessions
2. A satellite app which uses the central app to authenticate users

The Central App

Nothing special going on here. We have a Rails application which uses authlogic, and we have some basic CRUD screens setup to manage users, roles and permissions.

In your database.yml file define your database:

  development:
    adapter: sqlite3
    database: db/development.sqlite3
    pool: 5
    timeout: 5000

Make sure you are using the database to persist session information. To do this, add the following line to your config/environment.rb:

config.action_controller.session_store = :active_record_store

Then, create a sessions table in your database by running:

rake db:sessions:create

Finally, make a note of the session settings in your config/initializers/session_store.rb file. This is important because these will have to be the same across all the applications:

ActionController::Base.session = {
  :key         => '_session_key',
  :secret      => '_some_very_long_string'
}

The Satellite App

Any satellite app that is to use our central authentication app also needs to be using authlogic. However, there are a few tweaks we will make to redirect some of the magic to the central app.

In your config/initializers/session_store.rb file, make sure the session information matches that of your central app:

ActionController::Base.session = {
  :key         => '_session_key',
  :secret      => '_some_very_long_string'
}

We also need the following lines added to the config/initializers/session_store.rb file:

ActionController::Base.session_store = active_record_store
ActiveRecord::SessionStore::Session.establish_connection("sessions_#{RAILS_ENV}")

Modify your user.rb model to look like this:

class User < ActiveRecord::Base
  establish_connection "sessions_#{RAILS_ENV}"
  acts_as_authentic
end

Finally, define the databases in your database.yml file. You will need both the application database as well as the authentication database definitions:

development:
  adapter: sqlite3
  database: db/development.sqlite3
  pool: 5
  timeout: 5000
  
sessions_development:
  adapter: sqlite3
  database: ../auth_app/db/development.sqlite3
  pool: 5
  timeout: 5000

Helper methods

Finally, add the following helper methods to your ApplicationController models in both/all your applications:

helper_method :current_user

protected

def current_user_session
  return @current_user_session if defined?(@current_user_session)
  @current_user_session = UserSession.find
end

def current_user
  return @current_user if defined?(@current_user)
  @current_user = current_user_session && current_user_session.record
end

def require_user
  unless current_user
    flash[:error] = "You must be logged..."
    redirect_to root_path
    return false
  end
end

def require_no_user
  if current_user
    flash[:error] = "You cannot be logged in..."
    redirect_to root_path
    return false
  end
end

Viola! We now have a single sign on solution with shared sessions across multiple Rails applications. We also don’t use any cookies so this could easily work across multiple domains.

Summary

This is a simplified illustration of our solution. Obviously this is for applications within the same “portal”. This solution is not “secure”. If you plan on using something like this for production applications you should use HTTPS to secure your cookies.

I’m using SQLite here, but in production we use ODBC drivers, meaning we don’t have to have all the databases on the same server. Just a consideration to bear in mind.

About these ads

Tags: , ,

4 responses to “Rails, Authlogic and Single Sign On”

  1. Francesco Rigotti says :

    Great post!

    I’ve struggled for days to implement an SSO mechanism for a set of apps used in the company I work for. Your post saved me.

    I had to cope with a legacy authentication system, so no auth_logic for me.

    One suggestion, is to include :secure => true, in the session_options (this causes cookies not to be sent outside of https, therefore securing your application against session hijacking
    “uh? Firesheep? :D”)

    Since the code above is not all compliant with Rails3 and others might have the same issue of not being able to use auth_logic, I’ll show what my configs look like.

    Besides sharing the sessions at the model level, it is also necessary to share the cookie
    (a cookie is still sent by the browser, to provide the session_id, even it the session is stored with active_record)

    Central Application
    ——————————————-
    session_store.rb
    ….. session_store :active_record_store, :key => ‘_da_key’, :domain => “.company.top.domain”,
    :secure => true

    If your organization domain is myorg.com, put ‘.myorg.com’ as domain (leave the dot in front).
    With the domain option, all apps hosted on subdomains of myorg.com will share the cookie.

    secret_token.rb
    ….. secret_token = ‘da_secret’

    Satellite Applications
    ——————————————–
    session_store.rb
    ….. session_store :active_record_store, :key => ‘_da_key’, :domain => “.company.top.domain”,
    :secure => true

    ActiveRecord::SessionStore::Session.establish_connection “sessions_#{Rails.env}”

    secret_token.rb
    ….. secret_token = ‘da_secret’

    All the rest is equal to what you have (apart from the helper stuff, which I don’t use)

    Again, thanks a lot for the awesome and concise post!

  2. Todd Eichel says :

    Hi Ed, really appreciate this article. Looking forward to using some of the techniques, but what are the specific reasons that you “would not recommend using this solution for external, public applications”?

    Thanks!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: