Search code examples
pythondjangocsrf

How do I set a wildcard for CSRF_TRUSTED_ORIGINS in Django?


After updating from Django 2 to Django 4.0.1 I am getting CSRF errors on all POST requests. The logs show:

"WARNING:django.security.csrf:Forbidden (Origin checking failed - https://127.0.0.1 does not match any trusted origins.): /activate/"

I can't figure out how to set a wildcard for CSRF_TRUSTED_ORIGINS? I have a server shipped to customers who host it on their own domain so there is no way for me to no the origin before hand. I have tried the following with no luck:

CSRF_TRUSTED_ORIGINS = ["https://*", "http://*"]

and

CSRF_TRUSTED_ORIGINS = ["*"]

Explicitly setting "https://127.0.0.1" in the CSRF_TRUSTED_ORIGINS works but won't work in my customer's production deployment which will get another hostname.


Solution

  • The Django app is running using Gunicorn behind NGINX. Because SSL is terminated after NGINX request.is_secure() returns false which results in Origin header not matching the host here:

    https://github.com/django/django/blob/3ff7f6cf07a722635d690785c31ac89484134bee/django/middleware/csrf.py#L276

    I resolved the issue by adding the following in Django:

    SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
    

    And ensured that NGINX is forwarding the http scheme with the following in my NGINX conf:

    proxy_set_header X-Forwarded-Proto $scheme;