1

I've gone through a lot of other threads and discussion forums, but none solved exactly. This solution refers to few settings in the settings.py I've applied them, Django CSRF Cookie Not Set

I'm posting this question because I've tried other solutions but none exactly fixed it.

This is also a just the beginning of a server, I made the project, started an app, & created a view for POST request. Let me know if any other code is required...

My views.py nothing, just a basic return. When I add @csrf_exempt it works but I can't really do that.

from django.views.decorators.csrf import csrf_exempt
@csrf_exempt

views.py

from django.http import HttpResponse
import json


# Create your views here.
def Product(request):
    if request.method == "POST":
        try:
            data = json.loads(request.body)  # Parse JSON data from the request body
            if "data" in data:
                response_data = str(data["data"])  # Get the value of 'data' key
                return HttpResponse(response_data, content_type="text/plain")
            else:
                return HttpResponse(
                    "Invalid JSON data. 'data' key is missing.", status=400
                )
        except json.JSONDecodeError:
            return HttpResponse("Invalid JSON data.", status=400)
    else:
        return HttpResponse("This API only accepts POST requests.")

Settings.py

"""
Django settings for app_server project.

Generated by 'django-admin startproject' using Django 4.2.2.

For more information on this file, see
https://docs.djangoproject.com/en/4.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/
"""

import environ
from pathlib import Path

env = environ.Env()
environ.Env.read_env()

# 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.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env("SECRET_KEY")

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

SESSION_COOKIE_SECURE = None

SESSION_COOKIE_HTTPONLY = True

CORS_ALLOWED_ORIGINS = [
    "http://localhost:3000",
    # Add other trusted origins here if needed
]

CSRF_COOKIE_DOMAIN = [
    "http://localhost:3000",
    # Add other cookie domain here if needed
]

CSRF_TRUSTED_ORIGINS = [
    "http://localhost:3000",
    # Add other CSRF trusted origins here if needed
]

ALLOWED_HOSTS = [
    "*"
    # "localhost",
    # Add other allowed hosts here if needed
]

# Application definition

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "corsheaders",
    "rest_framework",
    "products",
]

REST_FRAMEWORK = {
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    "DEFAULT_PERMISSION_CLASSES": [
        "rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly",
    ]
}

MIDDLEWARE = [
    "corsheaders.middleware.CorsMiddleware",
    "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 = "app_server.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 = "app_server.wsgi.application"


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

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


# Password validation
# https://docs.djangoproject.com/en/4.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/4.2/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.2/howto/static-files/

STATIC_URL = "static/"

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

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

I'm making a request from React frontend as:

  function getCSRFToken() {
    const csrfCookie = document.cookie.match(/(^|;)csrftoken=([^;]+)/);
    return csrfCookie ? csrfCookie[2] : "";
  }

  const handleSubmit = (e) => {
    const csrfToken = getCSRFToken();

    fetch("http://127.0.0.1:8000/products/", {
      method: "POST",
      body: JSON.stringify({
        data: 1,
        info: "No",
      }),
      headers: {
        "Content-Type": "application/json",
        "X-CSRFToken": csrfToken,
      },
    }).then((response) => console.log(response));
  };

I've tried printing the csrfToken and it's valid. Thanks in advance.

Gourav Singh Rawat
  • 421
  • 1
  • 7
  • 17

1 Answers1

0

I think you need to pass API Base url not frontend url in CSRF_TRUSTED_ORIGINS

write

CSRF_TRUSTED_ORIGINS = ["http://192.168.1.155:8000/"] <- api base url (backend-url)

instead of

CSRF_TRUSTED_ORIGINS = [
    "http://localhost:3000",<- write here api base url (backend-url not frontend url)
    # Add other CSRF trusted origins here if needed
]
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "rest_framework.authentication.SessionAuthentication" # need for set cookies 
    ),
    "DEFAULT_PERMISSION_CLASSES": [
        "rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly",
    ]
}