I'm working on a system which will allow me to login to the same system via various domains. (www.example.com, www.mydomain.com, sub.domain.com etc)
The following threads form the basis of my research so far:
Single Sign On across multiple domains
Cross web domain login with .net membership
What I want to happen is that If I am logged in on the master domain and I visit a page on a slave domain to be automatically logged in on the slave.
Obviously If I am not logged in on the master, I will need to enter my username and password.
Walkthrough:
1. User logs in on master site
2. User navigates to slave site
3. Slave site re-directs to master site to see if User is logged in.
4. If User is logged in on master, record a RFC 4122 token ID and send this back to the slave site.
5. Slave site then looks up the token ID in the central database and logs this user in.
This might eventually end up running on more than once instance of PHP and Apache, so I can't just store:
token_id, php_session_id, created
Is there any problem with me storing and using this:
token_id, username, hashed_password, created
Which is deleted on use, or automatically after x seconds.
The basic idea is OK in the link you refer to but its also talking about session management too - forget about what to store in the database - all you need to do is enable sessions on master and clients. And store the authenticated username in the session (primarily so you can see if the user has been authenticated).
- User navigates to client site
- Client site re-directs to master site to see if User is logged in.
No - you only redirect from the slave site (calling it a client gets confusing) if slave site determines that the user has not been authenticated.
Forget about RFC 4122 - its just a clever way to get uuids which are being used in the post you refer to as session identifiers. PHP already generates perfectly good values.
You need to pass some sort of message back from the master to the slave which provides the user id and the fact that the user has been authenticated in the URL (you can't transfer cookies across domains and you can't do a POST in a redirect). One obvious way of doing this would be to have shared secret on both master and slave, then....
$redirect_to='http://slave.example.com/sso_lander.php?auth_token='
. encrypt($some_random_alphanum_chars
. '/' . $user . '/'
. time(), $shared_secret);
header("Location: $redirect_to", true, 303);
Then on the slave:
if (!($_SESSION['authenticated_user']) && $_GET['auth_token']) {
$auth_token=explode('/',decrypt($_GET['auth_token'], $shared_secret));
if ((abs($auth_token[2]-time())<3) {
// if more than 3 seconds after generate - DO NOT USE
$_SESSION['authenticated_user']=$auth_token[1];
}
}
Note the above is for illustration only - there is still a small window open for replay attacks and other things which should be tidied up- a better solution is that the slave generates a challenge which it stored in the local session and copies to the master. The master includes this in the encrypted reply. But the code for this is a bit more complex.
C.