I am testing on our staging server and am getting CSRF failures when trying to log in our proxy server or any CNAME pointing to it. The response is 403 Forbidden. This is the message I get when setting DEBUG=True
:
Referer checking failed - xhttp://www.app.com/accounts/login/?next=/ does not match xhttps://www.app.com/.
(“xhttp” is because the forum won’t let me post more than “2 links”… even though they’re not real links)
This is the nginx configuration:
upstream app_server {
server unix:/home/app/run/gunicorn.sock fail_timeout=0;
}
# proxy server to the django app server
server {
server_name proxy.staging.app.com;
listen 80 default_server;
location / {
include proxy_params;
proxy_set_header X-Forwarded-Port $server_port;
proxy_pass https://staging.app.com:8080;
}
}
# django app server
server {
server_name staging.app.com;
listen 80;
listen 8080 ssl;
listen 443 ssl;
# ssl certificates...
location / {
include proxy_params;
proxy_redirect off;
proxy_set_header X-Forwarded-Port $server_port;
proxy_pass http://unix:/home/app/run/gunicorn.sock;
}
}
# https redirect
server {
server_name staging.app.com;
listen 80;
return 301 https://$host$request_uri;
}
The http request is made to the proxy at proxy.staging.app.com which proxy passes with a https request to the block where the Django app runs (well, where it proxies to the socket running it).
As you can see, proxy headers are included so that the Django app knows the original host, scheme, port, etc. Relevant settings are also set:
USE_X_FORWARDED_HOST = True
USE_X_FORWARDED_PORT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
The reason CSRF validation fails seems to be that the addresses don’t match because of the scheme. I really don’t understand how this is happening: everything is configured correctly so that the original host and scheme is passed to Django, therefore why is it generating a CSRF token for the wrong address? Shouldn’t it be generating it for the original http address rather than the https one?