The way we develop our applications has changed significantly. To a great extent, we have adopted the service oriented design and generally have two or more applications communicating with each other. Now, if you have built-in authentication in your system, then you can either do a separate authentication for each application or have the single sign-on mechanism in place for all the applications.
Let’s see how we can implement the single sign-on for multiple applications. It is more about the concept rather than the code. Usually we are occupied with the thought of how to integrate our single sign-on or just look for the gems that can do the job for us. But once you get hold of the concept, I bet you will be happy to integrate it yourself.
Let’s begin!
By and large, our design will look something like as shown in the image below. You can easily tweak this idea to suit your service oriented design:
In this picture we can see that we have an authentication mechanism before client visits the main applications (App1, App2, App3). The main problem with the session is - "How can a session be maintained across all the applications, whether you have these applications as sub domain or in totally different domains?"
So how do we ensure the authentication from a single application for all our services?
First, authenticate the user from the authenticating application in the same way as you would do your single application, say you use devise. Once it is done, now you have to decide how, and to which application, you wish to redirect the user. There will be one users table and all the applications will have access to it. In addition to that, we can have a random temporary authentication token generated in the application. This token is strored in the user table each time a user logs in, and destroyed that token when the user logs out from the application. I suggest logout or session destroy method in each of your applications to protect your session from being compromised. In case user does not logout from the application, then devise automatically logs out the user after some time. Watch out for that and put an observer in your app to clean the token.
class sessionController < ... def create ... sign_in(user) current_user.generate_temporary_authentication_token ... end def destroy ... current_suer.clear_temporary_authentication_token sign_out(current_user) ... end end
In user model
class User def generate_temporary_authentication_token self.temporary_authentication_token = Devise.friendly_token self.save end def clear_temporary_authentication_token self.temporary_authentication_token = nil self.save end end
From your authentication application you redirect the user to one of the main applications;
Class WelcomeController < ... def redirect_user return redirect_to app_path, :token => current_user.temporary_authentication_token end end
Now in any of your main applications you can have something like this
class HomeController < ... def index token = params[:token] user = User.where( :temporary_authentication_token => token ).first return redirect_to authentication_app if user.blank? || token.blank? sign_in(user) end end
This code would be duplicated across the main applications. This is just a simple concept on how you can approach this single sign-on problem. You can figure out the areas where you need to put the kind of security and protect session hi-jacking. It’s mainly about maintaining the session in each of your applications.
The same concept can be applied on other platforms as well.
To me, it seems quite interesting to have a single authentication mechanism, and I welcome all the readers to provide their input on how it can be improved or implemented.