At The Group, we’re developing some web applications that needed to use the same user database. The applications were originally being developed with separate login for each, but I decided it would be better to share the login code across them.
I investigated some ways to achieve sharing a single login page over all these applications:
They all have some advantages and disadvantages, though…
A shared login library
This method basically involves two things: a main login site, and code for logging in which is shared amongst all apps.
The login site’s purprose is simple: to display the login form and redirect users back to the appliations – this way the applications won’t need to have their own login screens.
The login code on the other hand does a bit more: When a site needs a logged in user, it would first check if there’s an user. If not, it would invoke the login code which would handle the rest. The login code would redirect the user to the login site to fill in their information, which would then redirect back to the application, which would again run the login code, which in turn would validate the information passed from the form.
This approach is very simple. You only need the code to redirect the user a bit, and the login code itself could be put inside a single method of a class so implementation in an application would be relatively simple as well. It also works across domains, since there are no cookies or anything that have to be shared.
However, using this method, you won’t be able to automatically log the user in in your other application if they’ve logged in in one of them. This is because each site would be independent in regards to cookies and sessions.
This is the approach we chose to use at The Group, mainly because of the simplicity. However, we’ve made the library work so, that if deemed necessary, it will be simple to change authentication methods in the future, for example to utilize OpenID.
A custom CAS style setup
This one is more complex than the above. This would require your applications to send and receive data from the login site in the background, possibly making the whole process slower and less secure if any unwanted data was leaked or if the session verification isn’t done correctly.
The basic idea would be as follows:
- If the user is not authenticated:
The user would get redirected to the login site, which then displays the login form and authenticates the user. It would then redirect the user back to the main application itself, with a secret code in the url. The application would then take this code and in the background, use a socket connection to the login site to verify that the code is indeed correct.
- If the user is already authenticated, to any application:
Instead of showing the login form, the login site would establish the secret code and redirect the user back immediately. The application would then check the code with the server like in case #1.
This approach is similar to OpenID, so before you go and implement something like this yourself, I would look into OpenID to see if it would be good enough for your purproses.
The principle of OpenID is similar to the CAS one. However with OpenID, you can accept users from other OpenID providers than yourself. This way the user would not necessarily have to register an account with your site, but use his/her profile from another site they already are registered in, possibly saving some trouble from the user.
There are some ready to use OpenID libraries, such as Zend_OpenId, which can make implementing this easier. Also, OpenID doesn’t exactly do single sign-on, but if you create your own OpenID provider and do some tricks, it should be possible to automate the progress.
OpenID logins typically display the OpenID logo and differ slightly from more “traditional” login forms, but you could make it look like it’s not OpenID at all, that way taking advantage of the OpenID libraries. This way you could also open your logins in the future to support other OpenID providers even if you don’t find it necessary at the moment.