Monday, May 13, 2013

authentication - Cross-domain login using JSONP and cookies - Stack Overflow

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
 displayed on (or, etc) should POST
Step 2
On, the username and password are verified and a cookie is set on domain containing a unique value for that user. The user is then redirected back
SELECT unique_value FROM users WHERE username = $username
set cookie on containing unique_value
Step 3
Back on we embed a script call to

Step 4
On we check if the unique cookie is set for the user. Then we embed a JavaScript callback (JSON-P) that informs that the user is logged in. No sensitive user data is included, otherwise could embed this script and get the user's information. Instead, we create a disposable hash based on the timestamp, so that can verify the authentication.
if cookie on 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 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() {
} 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 containing unique_value
Step 6
The next time the user refreshes the page, we can bypass the JSON-P callback
if cookie on is valid
    loggedin = true
    delete cookie on
    proceed to Step 3

Logging Out

Step 7
The link on should go to
Step 8
On, not only is the cookie deleted, but the unique value for that user is reset. The user is redirected back to
delete cookie on
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, and the user is effectively logged out.


  1. It is critical that from Step 4 has the correct headers set so that it is not cached.
  2. 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.
  3. In Step 5, you can optionally store a unique cookie value on each domain.
  4. The separate 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.
  5. For this to work on Internet Explorer you will need a P3P policy attached to your cookies.
  6. 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 without you knowing, but that would be harmless.

No comments: