Company wide Single Sign On(SSO) using Devise custom authentication strategy

It is a common requirement to have a single sign on for multiple software services provided by a company, something like google account with multiple google services like gmail,docs,google+ . In order to do this it would be best to have a RESTful application responsible for authentication and have all other services authenticate against this application.

To authenticate users of our rails application against an external API we add a custom authentication strategy to devise. Devise is a flexible authentication solution for Rails based on Warden. Warden uses the concept of cascading strategies to determine if a request should be authenticated. Warden will try strategies one after another until either, – One succeeds – No Strategies are found relevant – A strategy Fails.

These are the steps to add custom authentication strategy.

1. Create your own strategy implementation inheriting from Devise::Strategies::Base

railsapp/lib/custom_auth.rb

moduleCustomAuth

  moduleDevise
    moduleStrategies
      classFromSession < ::Devise::Strategies::Base
        defvalid?
          # this strategy is only valid if there is a url_token
          # in the params hash.
          # e.g. http://myapp?url_token=mysecrettoken
          params[:url_token]
        end
        defauthenticate!         
          # lookup session data with external api
          session_data = get_session_data_from_api(params[:url_token])
          
          # check if token was valid and authorise if so
          ifsession_data['error']
            # session lookup failed so fail authentication with message from api 
            fail!(session_data['error'])
          else
            # we got some valid user data
            success!(User.find(session_data['user_id']))
          end
        end
      end
    end
  end
end
2. Add this strategy to warden
railsapp/config/initializers/devise.rb
config.warden do|manager|

  manager.strategies.add(:custom_auth, CustomAuth::Devise::Strategies::FromSession)
  manager.default_strategies(:scope=> :user).unshift :custom_auth
end
Devise flow diagram
Image
  1. The HTTP request enters the rack stack.
  2. Warden gets the request and forwards it in the rack stack, adding an environment variable “warden” that points to an authentication proxy.
  3. The request gets dispatched to the rails controller, which may call authenticate_user! from a filter. This is an alias for request.env[‘warden’].authenticate!(:scope => :user).
  4. The warden proxy picks an authentication strategy. Any strategy for which valid? returns true is tried.
  5. When authentication succeeds, a user object is returned to the controller. When it fails, the symbol :warden is thrown down the stack, and caught by the warden rack application. The latter will return a response, which is a redirect to the login page by default. This can be overridden by calling warden.custom_response!.
Testing custom authentication strategy
To test the custom authentication strategy use Fakeweb and get a list of responses from the external API an add different test cases.
References
Advertisements

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