#34855: Documenting CSRF_TRUSTED_ORIGINS relation to SECURE_PROXY_SSL_HEADER 
could
prevent misconfiguration when proxying HTTPs over HTTP
------------------------------------------------+------------------------
               Reporter:  jeroenmuller          |          Owner:  nobody
                   Type:  Cleanup/optimization  |         Status:  new
              Component:  Documentation         |        Version:  4.2
               Severity:  Normal                |       Keywords:  CSRF
           Triage Stage:  Unreviewed            |      Has patch:  0
    Needs documentation:  0                     |    Needs tests:  0
Patch needs improvement:  0                     |  Easy pickings:  1
                  UI/UX:  0                     |
------------------------------------------------+------------------------
 When the CSRF origin check fails, the documentation points in the
 direction of adding that origin to CSRF_ALLOWED_ORIGINS. However, as far
 as I understand this should only be neccessary if there are actually
 cross-origin requests. In practice the CSRF origin check may also fail
 when is proxying HTTPS traffic over HTTP without setting up
 SECURE_PROXY_SSL_HEADER accordingly. This problem may occur suddenly when
 upgrading to Django 4.0, because this version turns on the origin
 verification in the CSRF middleware. In that case the Django release notes
 point in the direction of adding the failing origin to
 CSRF_ALLOWED_ORIGINS: https://docs.djangoproject.com/en/4.2/releases/4.0
 /#csrf-trusted-origins-changes-4-0. But this is not the optimal solution,
 and may weaken CSRF protection if a user ends up just adding a pattern
 matching all subdomains or the complete ALLOWED_HOSTS lists to
 CSRF_ALLOWED_ORIGINS.

 It might be useful to add a note or warning below
 https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-
 CSRF_TRUSTED_ORIGINS explaining that it should only be neccessary to
 configure this if you are actually making requests across subdomains, and
 in other cases setting up SECURE_PROXY_SSL_HEADER might be a more
 appropriate solution (as long as the proxy correctly sets a header like X
 -Forwarded-Proto).

 I ran into this problem when I updated a project hosted behind AWS ELB
 load balancer and gunicorn to Django 4.0, and the CSRF origin checking for
 the Django admin stopped working in a staging environment, with the
 message `CSRF verification failed. Request aborted.`. I could not figure
 out what was going on using the documentation and ended up finding the
 root cause through a stackoverflow answer which pointed out that the
 origin header is compared against a string constructed of the host,
 prefixed by either http or https based on the result of
 ''request.is_secure()''

  - https://stackoverflow.com/a/71482883

 In my case, the proxy setup was forwarding requests over HTTP, so
 is_secure() was false and CSRF was comparing the origin `https://subdomain
 .my-domain.com` against "host" `http://subdomain.my-domain.com`. It seems
 like the best solution here is to use  SECURE_PROXY_SSL_HEADER to allow
 Django to determine if the client is using HTTPS or not, and use the
 "host" string `https://subdomain.my-domain.com` . Looking at the
 referenced stackoverflow thread, this is a recurring problem for users
 updating to Django 4.0 and many end up with the sub-optimal solution of
 adding the origin with https to CSRF_ALLOWED_ORIGINS explicitly.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34855>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/0107018ab15c43c1-a69362d8-017b-49a3-89d7-6185a3eefa40-000000%40eu-central-1.amazonses.com.

Reply via email to