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
displayed on mydomain.com
(or myotherdomain.com
, etc) should POST tocentral.com/login
Step 2
On
central.com/login
, the username and password are verified and a cookie is set on thecentral.com
domain containing a unique value for that user. The user is then redirected back tomydomain.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 script call to central.com/check
.
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. 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.
- 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.
No comments:
Post a Comment