Origin checking failed with SSL (https)

My site was working good with http. Until I installed the SSL certificate and now my POST requests are not working (GET works) but POST does not it shows 403 (CSRF ERROR) with these:
Origin checking failed - https://mysite.com does not match any trusted origins.

I’ve tried the CORS_ORIGIN_WHITELIST, CSRF_TRUSTED_ORIGINS and CSRF_ALLOWED_ORIGINS but nothing seems to work. Please someone help.

Thanks!

1 Like

Please post the actual settings you’ve made for those entries.

(When posting code here, surround the code between lines of three backtick - ` characters. This means you’ll have a line of ```, then your code, then another line of ```. This forces the forum software to keep your code properly formatted.)

Here they are, btw I’m using Django channels and ASGI:

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '####'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ["https://myside.com"]
CSRF_TRUSTED_ORIGINS = ["https://mysite.com"]


# Application definition

INSTALLED_APPS = [
    'channels',
    
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.humanize',

    'django_countries',
    'mathfilters',

    'main',
    'account',
    "chat",
    "forum",
    "administrator",
]

ASGI_APPLICATION = 'mysite.asgi.application'

CHANNEL_LAYERS = {
    'default' : {
        'BACKEND': 'channels.layers.InMemoryChannelLayer'
    }
}

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'mysite.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            BASE_DIR / "templates"
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'main.context_processors.global_vars'
            ],
        },
    },
]

WSGI_APPLICATION = 'mysite.wsgi.application'


# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}


# Password validation
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/4.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/

STATIC_URL = 'static/'

STATICFILES_DIRS = [
    BASE_DIR / "static/"
]

STATIC_ROOT = BASE_DIR / "staticfiles/"

MEDIA_URL = "uploads/"
MEDIA_ROOT = BASE_DIR / "uploads/"

# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'


# CUSTOM VARS
POST_FILE_ALLOWED_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "mp4", "mkv", "mov", "avi"]
CHAT_FILE_ALLOWED_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "mp4", "mkv", "mov", "avi", "pdf"]

ABSOLUTE_URL_OVERRIDES = {
    'auth.user': lambda u: "/@%s/" % u.username,
}
1 Like

See ALLOWED_HOSTS - the protocol is not part of the specification for that setting.

You mention CSRF_ALLOWED_ORIGINS and CORS_ORIGINS_WHITELIST in your original post, but I see nothing in your settings relating to that.

You may also want to review the docs at How to use Django’s CSRF protection | Django documentation | Django

Side note:

It’s an extremely bad idea to still have this in your settings at this point of your progress.

I’m aware of the InMemoryChannelLayer. But the CSRF_ALLOWED_ORIGINS, i have removed them since they were not working. Also I’ve tried without the protocol in ALLOWED_HOST. But nothing still works

Is CORS an issue here? Are you loading JavaScript from a different site that needs to make requests to your site?

Regarding the CSRF_TRUSTED_ORIGINS, it is needed. (I made a mistake, there is no CSRF_ALLOWED_ORIGINS.)

It will also be helpful if you show how you’re doing the post to Django. Is it a form being posted or some type of AJAX call?

I’m using AJAX. I’m using Django’s default jinja for frontend.

It works in localhost, in the server as well (without the https) but when https it does not work.

Two very different situations internally to Django. That’s why we need to see the code doing the post.

Which codes you mean? In which file, please let me know.

The JavaScript that is doing the post. (I wouldn’t know what file you have that in.)

I’m using this function getData. Here are the codes for that:

function getCookie(name) {
        let cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            const cookies = document.cookie.split(';');
            for (let i = 0; i < cookies.length; i++) {
                const cookie = cookies[i].trim();
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    const csrftoken = getCookie('csrftoken');

    $(document).ready(function(){
        $.ajaxSetup({
            type: "POST",
            headers: {'X-CSRFToken': csrftoken},
            dataType: "json"
        });
    })


    const getData = (url, data, success, error) => {
        $.ajax({
            url: url,
            data: data,
            type: "POST",
            headers: {'X-CSRFToken': csrftoken},
            success: success,
            error: error,
        });
    }

And what are you currently using for your CSRF_TRUSTED_ORIGINS and ALLOWED_HOSTS setting?

Yes you are correct, I have those in my settings.py

Hello, did you got a chance to check into it?

Please help me with this.

Please post your CSRF_TRUSTED_ORIGINS and ALLOWED_HOSTS settings.

I figured it out.
You are right, it was the ALLOWED_HOST and CSRF_TRUSTED_ORIGINS.but whenever I changed something in the settings.py, I only restarted my nginx but not the gunicorn. I knew I was missing something so I went through everything that I had done to serve this on the internet. And then gunicorn flashed into my mind. Now it’s working.

For anyone who is having the same problem, I added these:

ALLOWED_HOSTS = ["mysite.com"]
CSRF_TRUSTED_ORIGINS = ["https://mysite.com"]
CSRF_ALLOWED_ORIGINS = ["https://mysite.com"]
CORS_ORIGINS_WHITELIST = ["https://mysite.com"]

And then restarted the nginx and gunicorn and it’s working now.

Thanks

6 Likes

This one worked perfectly for me. Thanks @kachkolasa

Also with Django >= 5.0 I found that one more field in settings affected it:
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

1 Like

@aantsiferov you got it!

With Django 5+ the below is required for any HTTPS.
SECURE_PROXY_SSL_HEADER = (‘HTTP_X_FORWARDED_PROTO’, ‘https’)

Problem solved thank you!

I was following google cloud instruction for django, none of them mentioned about these 3 items. Thank you so much.

1 Like