简体   繁体   中英

Set-Cookie is not working in Chrome - with two websites

I have a problem with Set-Cookie not working in Chrome (I didn't check other browsers). It worked in the past but it stopped working recently. I have two websites with two domain names, and I need to set the cookie in both websites. I'm calling a URL in each of the domain names to set the cookie. But it doesn't set the cookie on the other website (the website I'm not browsing now).

The users login or logout or sign up to one website, and I want them to login or logout from the other website too, automatically. Currently if they login or logout to one website, it doesn't affect the other website.

The Django view code is:

@csrf_exempt
def set_session(request):
    """
    Cross-domain authentication.
    """
    response = HttpResponse('')
    origin = request.META.get('HTTP_ORIGIN')
    if isinstance(origin, bytes):
        origin = origin.decode()
    netloc = urlparse(origin).netloc
    if isinstance(netloc, bytes):
        netloc = netloc.decode()
    valid_origin = any(netloc.endswith('.' + site.domain) for site in Site.objects.all().order_by("pk"))
    if (not (valid_origin)):
        return response
    if (request.method == 'POST'):
        session_key = request.POST.get('key')
        SessionStore = import_module(django_settings.SESSION_ENGINE).SessionStore
        if ((session_key) and (SessionStore().exists(session_key))):
            # Set session cookie
            request.session = SessionStore(session_key)
            request.session.modified = True
        else:
            # Delete session cookie
            request.session.flush()
    response['Access-Control-Allow-Origin'] = origin
    response['Access-Control-Allow-Credentials'] = 'true'
    return response

And the JavaScript code is:

window.speedy = {};

window.speedy.setSession = function (domain, key) {
    $.ajax({
        url: '//' + domain + '/set-session/',
        method: 'post',
        data: {
            key: key
        },
        xhrFields: {
            withCredentials: true
        }
    });
};

Then there is a JavaScript code that calls this function twice:

speedy.setSession('speedy.net', 'session_key');
speedy.setSession('speedymatch.com', 'session_key');

Where 'session_key' is replaced by the session key of the user.

Is there any solution to this problem? I think this is due to recent changes in Chrome.

Update: We have a staging server where both the websites domains are subdomains of the same registered domain name. And there, Set-Cookie works fine. But in the production websites, I think the other site's cookies are blocked by Chrome because the other site's domain is different from the domain the user is currently browsing.

I checked and the cookies from the other website also don't work with Firefox and Dolphin. It might be related to the upgrade to Django 2.1 which we upgraded recently.

The same origin policy for cookies being triggered here; from a domain you can set cookies for:

  • own domain
  • parent domain (unless the parent domain is a (g)TLD)

So as the two domains in question do not share the parent-child relationship and the only common parent of them could be the TLD (assuming same TLD), you can't do this.

From MDN doc :

Cookies use a separate definition of origins. A page can set a cookie for its own domain or any parent domain, as long as the parent domain is not a public suffix. Firefox and Chrome use the Public Suffix List to determine if a domain is a public suffix. Internet Explorer uses its own internal method to determine if a domain is a public suffix. The browser will make a cookie available to the given domain including any sub-domains, no matter which protocol (HTTP/HTTPS) or port is used. When you set a cookie, you can limit its availability using the Domain, Path, Secure and Http-Only flags. When you read a cookie, you cannot see from where it was set. Even if you use only secure https connections, any cookie you see may have been set using an insecure connection.

Thanks to @aaron I found out the problem. This problem started only recently, after I upgraded Django to 2.1. Django 2.1 introduced the SESSION_COOKIE_SAMESITE setting, which must be set to None for our websites to work properly with session cookies. On the other hand, CSRF_COOKIE_SAMESITE for our websites can be set to 'Strict' , since we use separate CSRF cookies for each website. Therefore, I added the following lines to our base settings:

SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = None

CSRF_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'Strict'

From those lines, only SESSION_COOKIE_SAMESITE = None is necessary to fix the problem I mentioned in this question. I relied on the default setting of Django 2.1 to the value of SESSION_COOKIE_SAMESITE , which was not working for us in this case.

Currently the login and logout works in Chrome on my desktop and in one mobile phone. But I checked another mobile phone I have, and there it doesn't work - the problem persists as it was before. I'm not sure if this is due to a personal settings in this mobile phone or in the Chrome app? But login and logout to both websites simultaneously doesn't work there. If I login to one website, I'm still logged out from the other website, and vice versa.

Currently the login and logout works in Chrome. The problem was cookies settings - check your settings at chrome://settings/cookies (desktop) or settings > site settings > cookies (mobile).

(August 2020) Update: It is now required to use the following settings for Chrome. Please see this question and answer .

SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = 'None'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM