How to avoid CSRF token issues with Django when running on different sub-domains

Posted on 2022-02-13 in Trucs et astuces

If you deploy multiple Django websites on your infrastructure on various subdomains, you may get issues about invalid CSRF tokens. This is happening either because:

  • You erase the cookie by using the same domain. For instance, if you have your prod API at api.jujens.eu and pre-production one at preprod-api.jujens.eu and set the CSRF cookie on .jujens.eu. This is required you have a frontend app on its dedicated domain (let's say app.jujens.eu and preprod-app.jujens.eu) and need it to send the CSRF token in the header as described here.
  • You have multiple cookies and thus will send a valid or invalid ones at random. This can happened when you set your production cookie on .jujens.eu and your pre-production ones on .preprod.jujens.eu. Your browser, when on app.preprod.jujens.eu will see both cookies since their domain allow it. As far as I know, there is no way to select the domain when reading cookies with JavaScript, so you are stuck.

Note

Auth is not concerned by this, because its cookie will always be linked to a specific domain (eg api.jujens.eu) and thus won't be sent to any other domain. I think that even if you do weird stuff and do things like this preprod.api.jujens.eu, you should be fine because the cookie is strictly tied to the domain and not any subdomain like it would with .api.jujens.eu.

How do you prevent these issues? By changing the cookie name. You can add a different CSRF_COOKIE_NAME in your settings for each Django instances. For instance: CSRF_COOKIE_NAME=f"csrf-${ENVIRONMENT}". You will then need to inject this cookie names in your frontend so it knows which one to read. See the documentation for more details.

I hope you found it useful. Please comment if you have a question.