How can I allow users to log into one domain and automatically be logged into my other domains without them having to submit a form on each domain?
1 回答
We all know that cookies are not accessible cross-domain as this presents a security risk. However, using some trickery, there are ways around this. Basically we are setting a cookie for the user on a central domain, checking for that cookie's existence using a script, then using a JSON-P callback to copy that cookie onto the other domains. In more detail:
Logging In
Step 1
The <form>
displayed on mydomain.com
(or myotherdomain.com
, etc) should POST to central.com/login
Step 2
On central.com/login
, the username and password are verified and a cookie is set on the central.com
domain containing a unique value for that user. The user is then redirected back to mydomain.com
SELECT unique_value FROM users WHERE username = $username
set cookie on central.com containing unique_value
Step 3
Back on mydomain.com
we embed a javascript call to central.com/check
.
<script type="text/javascript" src="http://central.com/check"></script>
Step 4
On central.com/check
we check if the unique cookie is set for the user. Then we embed a JavaScript callback (JSON-P) that informs mydomain.com
that the user is logged in. No sensitive user data is included, otherwise hacker.com
could embed this script and get the user's information. (Setting appropriate Access-Control headers to only allow verified domains can alleviate this risk.) Instead, we create a disposable hash based on the timestamp, so that mydomain.com
can verify the authentication.
if cookie on central.com is valid
user_data = array(
'success' => true,
'uid' => $uid,
'time' => time_stamp,
'hash' => disposable_salted_hash( $uid, time_stamp )
)
echo 'setDomainCookie(' . json_encode(user_data) . ')'
Step 5
The callback function is then executed, setting the cookie on mydomain.com
. Finally, we can either refresh the page or just alert the user using JavaScript that they are logged in (preferably both).
function setDomainCookie( user_data ) {
if( user_data.success ) {
$.post('/setcookie', user_data, function() {
location.reload(true);
}
}
}
mydomain.com/setcookie
is similar to Step 2. Of course this assumes both sites have access to the same database (and code)
if hash = disposable_salted_hash( $uid, time_stamp )
SELECT unique_value FROM users WHERE uid = $uid
set cookie on mydomain.com containing unique_value
Step 6
The next time the user refreshes the page, we can bypass the JSON-P callback
if cookie on mydomain.com is valid
loggedin = true
else
delete cookie on mydomain.com
proceed to Step 3
Logging Out
Step 7
The link on mydomain.com
should go to central.com/logout
Step 8
On central.com/logout
, not only is the cookie deleted, but the unique value for that user is reset. The user is redirected back to mydomain.com
delete cookie on central.com
UPDATE users SET unique_value = new_random_value() WHERE username = $username
Step 9
Now that the unique value is reset, Step 6 from above fails, the cookie is also deleted from mydomain.com
, and the user is effectively logged out.
Notes
It is critical that
central.com/check
from Step 4 has the correct headers set so that it is not cached.Steps 3-5 when the user is logging in may cause a slight delay. It's wise to both refresh and show some kind of JavaScript alert that they are logged in. It's also important for the script from Step 3 to be as close to the top of the page as possible.
In Step 5, you can optionally store a unique cookie value on each domain.
The separate
central.com
domain is not really necessary; you can just use one of the other domains as the central domain if you wish. The logic for that domain would obviously be different.For this to work on Internet Explorer you will need a P3P policy attached to your cookies.
As IvanGusev points out in the comments, one flaw of this approach is that if the user logs out of device A, it will also log them out of every other device.
Hope this is helpful to people. I'd be very interested to receive feedback, especially if there are any security flaws from this method. I think the worst a hacker could do is replicate Steps 3-5 and log you in to
mydomain.com
without you knowing, but that would be harmless.