Hello everyone,
For a while I've been developing a system which allows a Drupal website to act as an authentication server and allow client websites to be connected to it. Once you register an account on one of the websites in the network you can use those credentials to gain access to any other website there.
I am writing this post because:
- We (Adulmec) are going to open source it so it makes sense to see if what we've done is of interest to you.
- I am not sure that some of our decisions are right and there might be better approaches which I did not see.
The base requirements were:
- Simple to use, just enter your username and password
- People can have different usernames on the websites in the network.
- Clients should not be Drupal necessarily.
- It should be secure.
- It should allow the synchronization of profile fields.
We considered OpenID and LDAP before doing our own system but in the end we decided a custom solution would better fit our needs.
The end result is a Drupal application which uses Services and the XMLRPC gateway, Job queue and Profile. A client website requires the client module which uses Services, Job queue and, optionally, Content Profile and Content Profile Registration. It can work with other languages as well and a Python client lib is on it's way.
The basic workflow is the following:
- When a user creates an account on a client website the data is sent to the auth server where a new user account is created. The name and the uid from the client website is stored in profile fields. Also, the initial website is stored as well.
- When a user goes to a client website and tries to login a check is performed on the site and if the remote auth succeeds a new account is created for him and the remote account gets updated with a new user / uid pair.
- Validation on user register / edit queries the server as well.
- When a user changes his information the updated information is sent to the remote server which propagates the changes to the other client websites where he has an account.
- A user has an overview page on each client website which shows him where he has accounts and what usernames he uses.
- A user can change his username locally (just for one site) or globally (on all sites he has an account).
There is also support for the content profile module. This works like this: on the auth server you create a cck type and add the fields you need to it. Then, on the client website, you map the local fields from profile types to the remote fields. They are synced on updates and new accounts also get a profile created and filled with the remote data automatically. There is also support for profiles showed on the registration page.
Right now the system requires the client to have an xmlrpc interface exposed as well, something which I don't like very much. However it was the only way I could make sure the updated information from the server gets to the client website immediately. One idea which I've toyed with was fetch updated information only on login but most people will be logged on multiple websites when they make a change and because of that it will be a while until the information is propagated.
If an update fails (server or client is down) the job is scheduled and is run a maximum number of times (configurable) until it bails out.
We are considering two approaches in storing the password:
1) Store the passwords both on the client and the server. This is nice because we can login them without doing a remote query and because they can still login even if the auth server is down. The disadvantage is that when someone changes his password he will be logged off from all the other websites he's logged on.
2) Store the password just on the server. Advantages are that the password is not going to be sent around the wire and changing it doesn't log you off from other websites. However you can't login when the server is down.
I also am not sure whether the "schedule the job a number of times" approach is good. Assume the server is down and we don't store the password. Most users will require a new password, use the one time login link and change the password. The update job will fail, be rescheduled x times (5 is the default) and if the auth server does not come back online during that time the new password will be "lost".
Another problem is the fact that we wanted the communication between sites to be secure. Since the communication is done both ways and we couldn't impose on the client websites to get ssl certificates I came up with another solution which works pretty well for now but is not as "clean" as I would like it. Basically each website gets a public / private ssl key. The parameters are serialized using json (for compatibility with other languages) and then they are encrypted with the private key. The other party uses the public key to decrypt the information and then it deserializes it.
Thanks for reading. What would you like to see in such a system? Do you have better ideas for the areas which I find problematic?
Comments
*_*
Have a look at http://drupal.org/node/286145, if it can help you.
Regards.
:)
Beautifulmind
BeautifulMind