Django and CORS

Hello guys,

This is my first post, I came here looking for some help, I have been working with Django for the last 4 years I think, I love it. I have made several web applications, I am mostly a backend developer.

I have been trying to acomplish something without success.

How can I make Django works as a normal Rest API without using django-cors-headers package and also avoid the use of the DRF?

I just want to access the backend urls without passing the CSRF token and without placing the exempt decorator to each function/view.

I just want to use the url in ajax requests without being blocked by the browser because of the CORS.

Hope you can help me.

Thank you.

All of the CSRF handling is done in the CsrfViewMiddleware. First step would be to remove that from your MIDDLEWARE settings. As I have never done this, I don’t know what other steps may need to be taken.

(You may still need / want to use the django-cors-headers package. The CORS header is what gives permission to JavaScript in the browser to make certain requests. You either need to use it, or run your system behind an http proxy that would add that header to the response.)

I just hope you fully understand the implications of doing this in the context of the system you are building.

Hey Ken, thank you, let me tell you a short history.

As I said, I am a backend developer, I have a very limited experience with frontend development.
Months ago I was developing a backend for a website frontend made in React, I expended a whole week with the frontend developer because he was unable to integrate my backend urls, bassicaly GET/POST methods, I installed the django-cors-headers performed all the configurations to allow the use of the backend, but the cookies(csrftoken & sessionid) was not getting settled by the browser. Something was blocking it and I was unable to determine why.

The solution was to make a middleware between his frontend and my backend, he made it.

I know the security reasons of why to use the csrf, I am agree with it, but I was just wondering if there is an alternative to make it work without this CORS issue without compromissing the security.

Thanks
Martin

Keep in mind that each of these topics are separate and distinct issues:

  • Cookies
  • CSRF
  • CORS

Problems with one are not addressed by making changes to the others.

1 Like

I see, but those issues are chained, right?
So, should I start by checking the cookies issue first?
Thanks

Not necessarily.

A CORS issue only applies if the JavaScript code loaded from one site is trying to make an AJAX call to a different site.

A CSRF issue only applies if you’re not getting the proper token from a site when you try to post to that site. It really doesn’t depend upon where the JavaScript was loaded from originally.

And I’m not sure what the “cookie” issue might be, other than a cookie set by one site is not visible and is not supposed to be leaked to any other sites.

But I remember that I tried to allow all hosts to access the urls in the CORS settings and had the same issue, the browser was not storing the cookie, so the ajax wasn’t able to access the cookie jar containing the csrf and the sessionid.

The problem is, how to allow all the hosts on the backend to avoid the CORS issue

This settings file was the one I used:


from pathlib import Path
import pymysql
import os

BASE_DIR = Path(__file__).resolve().parent.parent


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

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
WILL_MIGRATE = False  # to prepare migrations and deactivate apps native checking on startup

ALLOWED_HOSTS = [
    'example.us',
    'www.example.us',
    'example-us.vercel.app',
    'localhost',
    '*'
]

CORS_ORIGIN_ALLOW_ALL = True
CORS_REPLACE_HTTPS_REFERER = True
CSRF_TRUSTED_ORIGINS = [
    'https://localhost',
    'https://example-us.vercel.app',
    'https://example.us', 
    'https://www.example.us', 
    'https://www.example.us:40001',
    'https://example.us:40001',
    'https://0.0.0.0:40001',
]
CORS_ALLOW_HEADERS = [ "accept", "referer", "accept-encoding", "authorization", "content-type", "dnt", "origin", "user-agent", "x-csrftoken", "x-sessionid", "x-requested-with"]
CORS_EXPOSE_HEADERS = ['Set-Cookie']
"""
CORS_ALLOWED_HOSTS = [
    'example.us',
    'www.example.us',
    'example-us.vercel.app',
    'localhost'
]
CORS_ALLOWED_ORIGINS = [
    'https://localhost',
    'https://example-us.vercel.app',
    'https://example.us', 
    'https://www.example.us', 
    'https://www.example.us:40001',
    'https://example.us:40001',
    'https://0.0.0.0:40001',
]

CORS_ALLOW_CREDENTIALS = True

CSRF_TRUSTED_ORIGINS = [
    'localhost', 
    'www.example.us', 
    'example.us'
]
"""
"""
# old testing settings
CSRF_COOKIE_SECURE = True

ALLOWED_HOSTS = [
'example.us',
'www.example.us',
# 'www.example.us:40001',
  'example-us.vercel.app'
]

CORS_ALLOWED_HOSTS = [
'example.us',
'www.example.us',
# 'www.example.us:40001',
  'example-us.vercel.app'
]
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOWED_ORIGINS = [
  'https://127.0.0.1:3000',
  'https://example-us.vercel.app',
  'https://example.us', 
  'https://www.example.us', 
  'https://www.example.us:40001',
  'https://example.us:40001'
]

CSRF_TRUSTED_ORIGINS = [
  'example.us', 
  'www.example.us', 
  'vercel.app',
  'example-us.vercel.app'
]
# SESSION_COOKIE_SAMESITE = "strict"
"""
"""
CORS_ALLOWED_HOSTS = [
  'https://127.0.0.1:3000',
  'https://example-us.vercel.app',
  'example.us', 
  'www.example.us', 
  'www.example.us:40001'
]

CSRF_TRUSTED_ORIGINS = [
  'https://127.0.0.1:3000',
  'https://example-us.vercel.app',
  'https://example.us/', 
  'http://example.us/', 
  'https://www.example.us/', 
  'http://www.example.us',
  'https://www.example.us:40001',
  'http://www.example.us:40001'
]
# CSRF_COOKIE_SAMESITE = None
CORS_ORIGIN_WHITELIST = (
  'https://127.0.0.1:3000',
  'https://example-us.vercel.app',
  'https://example.us/', 
  'http://example.us/', 
  'https://www.example.us/', 
  'http://www.example.us',
  'https://www.example.us:40001',
  'http://www.example.us:40001'
)
CSRF_ALLOWED_ORIGINS = [
  'https://127.0.0.1:3000',
  'https://example-us.vercel.app',
  'https://example.us/', 
  'http://example.us/', 
  'https://www.example.us/', 
  'http://www.example.us',
  'https://www.example.us:40001',
  'http://www.example.us:40001'
]
"""
# CORS_ALLOW_HEADERS = [ "accept", "referer", "accept-encoding", "authorization", "content-type", "dnt", "origin", "user-agent", "x-csrftoken", "x-requested-with", "csrfmiddlewaretoken"]


"""
CORS_ALLOWED_ORIGINS = [
    "https://example.us:40001",
    "https://www.example.us:40001",
    "https://localhost:40001",
    "https://127.0.0.1:40001",
    "https://example-us.vercel.app"
]
"""

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blacklist',
    "corsheaders",
    'sslserver',
    'logs',
    # 'oauth',
    # 'allauth',
    # 'allauth.account',
    # 'allauth.socialaccount',
    # 'allauth.socialaccount.providers.google',
    'system',
    'cbapi',
    'authentication',
    'users',
    'emailservice',
    'userhelp',
    'services',
    'smsrequests',
    'usertransactions',
    'notifications',
    'permissions',
    'staff',
    'reports',
    'emt',
    'sims',
    'cryptogateway',
]

MIDDLEWARE = [
    "webapi.middlewareForCookies.CustomHeaderMiddleware",
    "corsheaders.middleware.CorsMiddleware",
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'blacklist.middleware.BlacklistMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'webapi.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        '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',
            ],
        },
    },
]

WSGI_APPLICATION = 'webapi.wsgi.application'


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

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'pre_production_webapi',
        'USER': 'pre_production_webapi',
        'PASSWORD': 'pre_production_webapi',
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}


pymysql.version_info = (1, 4, 2, "final", 0)
pymysql.install_as_MySQLdb()



# Password validation
# https://docs.djangoproject.com/en/3.2/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/3.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')

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

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'


# extra apps settings

# time to wait to close the account
ACCOUNTS_CLOSING_GRACE_PERIOD = 2592000  # seconds, 2592000 = 30 days

I’m still not clear on what the precise situation and issue is here. (e.g. What cookie are you talking about here?) A more precise explanation of the issue might be helpful along with posting the complete error messages being generated in the browser and/or the server.

But in general terms, it appears like your CORS_ALLOW_CREDENTIALS and CORS_ALLOWED_ORIGINS settings are commented out. If you need to include credentials, then the credentials setting is needed.

Also, depending upon your usage of those cookies, you may want to look at relaxing the security of the cookies - see set_cookie.

You may also find this site of value: How to win at CORS - JakeArchibald.com There appears to be a lot of useful (and readable) information there.

have you solved this issue? because i have this problem(cookie that i set don’t arrive to the client) right now and three last days . I solved yesterday , but i am stupid and I rEedited settings.py . I need to know what configuration of cors or django-cors-headers i have to apply to setting.py . All application django work perfectly , its work only for chrome with no-cors-policy , i need to solve this issue to deploy in production.