Django + Caddy = CSRF protection issues
Become part of the top 3% of the developers by applying to Toptal https://topt.al/25cXVn
--
Music by Eric Matyas
https://www.soundimage.org
Track title: Puzzle Game 2 Looping
--
Chapters
00:00 Question
02:31 Accepted answer (Score 7)
04:34 Thank you
--
Full question
https://stackoverflow.com/questions/7258...
Accepted answer links:
[this function in the CSRF middleware]: https://github.com/django/django/blob/db...
[Caddy will always ignore]: https://caddyserver.com/docs/caddyfile/d...
[SECURE_PROXY_SSL_HEADER]: https://docs.djangoproject.com/en/4.0/re...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #django #docker #reverseproxy #caddy
#avk47
--
Music by Eric Matyas
https://www.soundimage.org
Track title: Puzzle Game 2 Looping
--
Chapters
00:00 Question
02:31 Accepted answer (Score 7)
04:34 Thank you
--
Full question
https://stackoverflow.com/questions/7258...
Accepted answer links:
[this function in the CSRF middleware]: https://github.com/django/django/blob/db...
[Caddy will always ignore]: https://caddyserver.com/docs/caddyfile/d...
[SECURE_PROXY_SSL_HEADER]: https://docs.djangoproject.com/en/4.0/re...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #django #docker #reverseproxy #caddy
#avk47
ACCEPTED ANSWER
Score 11
Finally found out what was happening.
I first wanted to know the exact HTTP request that was sent from caddy to django:
sudo tcpdump -i lo -A -n port 8088
This confirmed that:
- the
OriginandRefererheaders were set properly - the
csrftokencookie was sent properly
Once that was known, I could dig in the code from django. Specifically, this function in the CSRF middleware.
In conclusion:
- Caddy forwards the http request to django unencrypted (so HTTP-non-S between caddy and django).
- Django considers that request non-secure
- The CSRF protection expects the
Originheader sent by the browser to behttp://because the request is not secure. In my case, it ishttps://because my browser is talking to Caddy over https - Because the
Originheader does not match what the CSRF middleware expects, the request is rejected
It's actually a simple fix.
Since we know that Caddy will always ignore X-Forwarded-Proto from the browser and sets it itself, we can add SECURE_PROXY_SSL_HEADER to the settings.py in django:
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
And voilĂ !
Now I can also set these to true:
- SECURE_SSL_REDIRECT
- SESSION_COOKIE_SECURE
- CSRF_COOKIE_SECURE
EDIT Here's the Caddyfile, as per requested:
service.mywebsite.com {
reverse_proxy localhost:8088
}