Search code examples
javascriptdjangogoogle-chromecookiesdolphin-browser

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


Please see this question and answer from 8 months ago. The answer fixed the problem for a while, but today I discovered that login and logout works again separately for each of my websites (domains), in Chrome and in Dolphin. But, everything works as before in Firefox, Edge and Opera. Did something change in those browsers regarding cookies from other domain names and how do I fix it so that login and logout will work simultaneously in both websites?

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, and it works with Firefox, Edge and Opera. But users of Chrome and Dolphin, 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.

And Django settings (with Django 3.0.6):

SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = None

CSRF_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'Strict'

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

I checked and I get the following errors from the console:

From Speedy Match From Speedy Net

It looks like related to the following links:


Solution

  • A cookie ... was set without the `SameSite` attribute.

    Starting July 14 (2020), you should set these 1,2 and upgrade to Django 3.1 3,4 (released Aug 4):

    SESSION_COOKIE_SECURE = True
    SESSION_COOKIE_SAMESITE = 'None'
    

    Explanation

    Before Django 3.1, the samesite attribute is not set if the setting is the None singleton:

    if samesite:
        if samesite.lower() not in ('lax', 'strict'):
            raise ValueError('samesite must be "lax" or "strict".')
        self.cookies[key]['samesite'] = samesite
    

    As of Django 3.1, the samesite attribute is set for the 'None' string; still not for None/False:

    if samesite:
        if samesite.lower() not in ('lax', 'none', 'strict'):
            raise ValueError('samesite must be "lax", "none", or "strict".')
        self.cookies[key]['samesite'] = samesite
    

    References

    1. Cookies default to SameSite=Lax - Chrome Platform Status
    2. Reject insecure SameSite=None cookies - Chrome Platform Status
    3. Settings | Django documentation | Django #std:setting-SESSION_COOKIE_SAMESITE
    4. Allowed setting SameSite cookies flags to 'None' · Pull Request #11894 · django/django