Dynamic SESSION_COOKIE_DOMAIN and CSRF_COOKIE_DOMAIN settings

62 views
Skip to first unread message

Kevin Grinberg

unread,
Jun 2, 2020, 2:40:21 PM6/2/20
to Django developers (Contributions to Django itself)
Hi folks,

I recently ran into an issue around the SESSION_COOKIE_DOMAIN and CSRF_COOKIE_DOMAIN settings that seems like it could be fixable by adding some extensibility.

Before submitting a patch/PR, I wanted to get the community's opinion on whether this is worth addressing in the framework, or if it's adding complexity for an audience of ~1.

The issue is that I needed to set SESSION_COOKIE_DOMAIN and CSRF_COOKIE_DOMAIN to a different value depending on the request's Host header.

For example, imagine the same Django app serving two domains with two subdomains, e.g.:


For each request to *.example.com, I want to set SESSION_COOKIE_DOMAIN and CSRF_COOKIE_DOMAIN to 'example.com', and vice-versa for requests to *.example2.com

As it stands, if I set SESSION_COOKIE_DOMAIN and CSRF_COOKIE_DOMAIN to None (the default behavior), the cookie domain will be the full request host - so api.example.com won't see cookies from www.example.com, and vice-versa. Thus, if I want cross-domain cookies, I need to set [SESSION|CSRF]_COOKIE_DOMAIN to e.g. 'example.com' so that it's sent for both domains.

Right now, the only way to do that is by overriding CsrfViewMiddleware and SessionMiddleware almost wholesale, because the references to SESSION_COOKIE_DOMAIN and CSRF_COOKIE_DOMAIN are buried inside the middlewares' process_request/process_response methods.

I propose that this could be addressed by adding an e.g. 'get_cookie_domain' method to CsrfViewMiddleware and SessionMiddleware, which projects could override to get the sort of custom behavior I'm trying to enable here (the default would of course be to return the setting, as it does now).

I've considered and dismissed some alternative approaches - this seems like the cleanest way of accomplishing this without introducing a ton of new complexity.

I recognize that CSRF and session behavior is particularly fraught with security implications, so I wanted to throw this out to the community and see if there were any strong feelings one way or another before moving forward with a PR.

Cheers,
Kevin

Adam Johnson

unread,
Jun 2, 2020, 5:46:06 PM6/2/20
to django-d...@googlegroups.com
You can already achieve what you're aiming to do in an outer middleware by mutating the cookie in response.cookies. The cookie object can have its domain changed before it is sent to the client:

>>> from django.http import HttpResponse
>>> resp = HttpResponse()
>>> resp.set_cookie('foo', 'bar', domain='example.com')
>>> resp.cookies
<SimpleCookie: foo='bar'>
>>> resp.cookies['foo']
<Morsel: foo=bar; Domain=example.com; Path=/>
>>> resp.cookies['foo'].update({'domain':'example.org'})
>>> resp.cookies['foo']
<Morsel: foo=bar; Domain=example.org; Path=/>

In this way, you could even leave the setting as None and instead use an outer middleware to set the domain appropriately based on request.headers['host'] , for requests where the cookie is being set. You can even do it automatically for all outgoing cookies.


--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/0c16e9e4-b588-4cd0-ba9a-8c1287e6a193%40googlegroups.com.


--
Adam
Reply all
Reply to author
Forward
0 new messages