5

Background

I'm trying to configure my Django app to work with ssl provided by cloudflare. I have about the same setup as this answer and have followed the same solution.

Issue:

This has been killing me for weeks (please help!) as I am not a networking/security guy and just need a solution that will avoid me gouging my eyes out but keep the site secure.

I am currently getting a CSRF issue where https://www.domain.co.uk does not match https://domain.co.uk

Config

Settings.py

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
USE_X_FORWARDED_HOST = True

nginx:

server {

    listen 80 default_server;

    server_name domain.co.uk www.domain.co.uk;
    access_log off;

    location /static/ {
        alias /static/;
    }


    location / {
            proxy_pass http://127.0.0.1:8000;
            proxy_set_header X-Forwarded-Host $server_name;
            proxy_set_header X-Real-IP $remote_addr;
            add_header P3P 'CP="ALL DSP COR PSAa PSDa OUR NOR ONL UNI COM NAV"';

            proxy_set_header X-Scheme $scheme;
            proxy_set_header X-Forwarded-Protocol $scheme;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            }
}

Cloudflare DNS:

A domain.co.uk  points to <ip> Automatic
CNAME www is an alias of domain.co.uk Automatic 

Bonus

In addition I also have the .com for the domain and would like to know how best to set this up so that it is also ssl.

Community
  • 1
  • 1
Silian Rails
  • 897
  • 1
  • 8
  • 14

2 Answers2

5

You need to setup the domain which is sending the CSRF cookie. Try setting CSRF_COOKIE_DOMAIN to ".domain.co.uk" and CSRF_COOKIE_SECURE to True in your settings.

Relevant documentation https://docs.djangoproject.com/en/4.1/ref/csrf/#how-it-works

fasouto
  • 4,386
  • 3
  • 30
  • 66
1

Personally I would put your config on the nginx side, not the Django side. That way when you do local development you can verify your CSRF and make sure everything works. Make sure it does work...if you can't get it to work on local without the nginx config then there's another problem that isn't related to your server config. It should then be possible to make everything work the same way on the server without specific Django settings or libraries.

For your nginx config, the solution is probably to us an answer like this to 301 redirect all www. to non-www, as well as redirect all http to https.

Then, you can rename this line in your nginx:

server_name domain.co.uk www.domain.co.uk;

to:

server_name domain.co.uk;  # This assumes you're directing www. to non-www

which should solve your CSRF issues...because you'll only be referencing one domain vs. two as you were above.

The added benefit of the 301 redirects is that you avoid any duplicate content penalties for organic search.

[EDIT] It looks like you're using a CNAME to redirect www. to non-www, so you could simply use the https to non-https 301 redirect from the answer I referenced above.

Community
  • 1
  • 1
YPCrumble
  • 26,610
  • 23
  • 107
  • 172