32

In Django, I have SESSION_COOKIE_DOMAIN set to my domain name. But I would actually like to run the same site with two different domain names.

With SESSION_COOKIE_DOMAIN set, only the named domain allows the user to login. Is it possible to allow both domains to login?

interstar
  • 26,048
  • 36
  • 112
  • 180

4 Answers4

44

If you set your session cookie domain to start with a "." character it will let you handle wildcard sub-domains and share a session cookie (login session) across multiple subdomains.

In settings.py:
SESSION_COOKIE_DOMAIN=".stackoverflow.com"

The above would allow a cookie to be shared across user1.stackoverflow.com and user2.stackoverflow.com.

If you really do want the url's to be different for the same site, would you want the same user to switch between the two sites on one login session? Or do you just want the ability to have two different users login to the site from two different url's (that are not sub-domains?)

MikeN
  • 45,039
  • 49
  • 151
  • 227
  • I want the second. Not sub-domains. Basically I have a client who has averylongdomainnamethatno-onewantstotype.net and quickname.net and the site needs to work for both. – interstar Jan 27 '10 at 11:55
  • 7
    How about adding a redirect from `longname.net` to `shortname.net` so that all users only use `shortname.net`? – Burhan Khalid Aug 03 '13 at 03:25
  • Would work between `example.com` and `www.example.com` as well. – Hassan Baig Jan 23 '17 at 16:07
  • You should never have one web application accessible from multiple URLs. You choose either "www.example.com" or "example.com" and have one name redirect all requests to the other. – emyller Mar 24 '23 at 22:37
8

The standard SessionMiddleware only supports one SESSION_COOKIE_DOMAIN, which is only good for one domain and subdomains thereof.

Here's a variation that will set the cookie domain dynamically based on the request host. To use it, just update your MIDDLEWARE_CLASSES to use this one SessionHostDomainMiddleware, instead of SessionMiddleware. This better, @jcdyer and @interstar?

import time

from django.conf import settings
from django.utils.cache import patch_vary_headers
from django.utils.http import cookie_date
from django.contrib.sessions.middleware import SessionMiddleware

class SessionHostDomainMiddleware(SessionMiddleware):
    def process_response(self, request, response):
        """
        If request.session was modified, or if the configuration is to save the
        session every time, save the changes and set a session cookie.
        """
        try:
            accessed = request.session.accessed
            modified = request.session.modified
        except AttributeError:
            pass
        else:
            if accessed:
                patch_vary_headers(response, ('Cookie',))
            if modified or settings.SESSION_SAVE_EVERY_REQUEST:
                if request.session.get_expire_at_browser_close():
                    max_age = None
                    expires = None
                else:
                    max_age = request.session.get_expiry_age()
                    expires_time = time.time() + max_age
                    expires = cookie_date(expires_time)
                # Save the session data and refresh the client cookie.
                # Skip session save for 500 responses, refs #3881.
                if response.status_code != 500:
                    request.session.save()
                    host = request.get_host().split(':')[0]
                    response.set_cookie(settings.SESSION_COOKIE_NAME,
                            request.session.session_key, max_age=max_age,
                            expires=expires, domain=host,
                            path=settings.SESSION_COOKIE_PATH,
                            secure=settings.SESSION_COOKIE_SECURE or None,
                            httponly=settings.SESSION_COOKIE_HTTPONLY or None)
        return response
s29
  • 2,027
  • 25
  • 20
  • 1
    What he's asking for is exactly the use case the sites framework is designed to accommodate. Suggesting "don't do that," isn't helpful. – jcdyer Aug 01 '13 at 15:07
  • Actually no @jcdyer, with SESSION_COOKIE_DOMAIN set, he won't be able to use vanilla SessionMiddleware and sites framework. – s29 May 05 '15 at 04:46
  • After a decade, I don't think this works anymore. We've got this kind of setup and django 3.2 errors saying that you can't use the admin without `SessionMiddleware` so it's not detecting the subclass. – markwalker_ May 20 '21 at 16:05
4

I think this is what you are looking for, I took me hours to find it out

https://bitbucket.org/uysrc/django-dynamicsites

You knows who
  • 885
  • 10
  • 18
1

I am using django 3.1.4, it worked for me.

Create a middleware like this, I am creating inside my app utilities.middleware

class CrossDomainSessionMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        if response.cookies:
            host = request.get_host()
            # check if it's a different domain
            if host not in settings.SESSION_COOKIE_DOMAIN:
                domain = ".{domain}".format(domain=host)
                for cookie in response.cookies:
                    if 'domain' in response.cookies[cookie]:
                        response.cookies[cookie]['domain'] = domain
        return response

Now place this middleware above SessionMiddleware inside settings.py

'utilities.middlware.CrossDomainSessionMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',

Make sure you have these two variable in your settings.py

SESSION_COOKIE_DOMAIN = '.domain.com'
SESSION_COOKIE_NAME = 'domainsessionid'
Nitin Raturi
  • 1,505
  • 1
  • 7
  • 12
  • But when trying to remove the cookie, those cookie that you changed the domain, cannot be deleted as far as I tried. Do you have a solution for deleting them? Thanks. – Jason Liu Oct 25 '21 at 23:27