Django throwing a 403 error (CSRF Cookie not set) despite token being passed in request header from React/Vite app

So my situation is that I have a form in a react frontend trying to post some data to a Django backend. When the Django view is CSRF exempt, all functionality is fine. However, when I remove the exemption decorator, Django always throws a 403 error - CSRF cookie not set.

I have verified that there is indeed a token being passed in the request header, but for some reason the 403 error is still being thrown. I found a similar thread with a similar issue (Django and React: csrf cookie is not being set in request header), however from what I saw, I was already using the suggested fixes.

Firstly, I have a route set up to initially pass the CSRF token to the frontend, as follows:

@ensure_csrf_cookie
def get_csrf_token(request):
    csrf_token = get_token(request)
    return JsonResponse({'csrfToken': csrf_token})

Along with the following JS to request the token:

const getCSRFToken = async () => {
    const apiUrl = import.meta.env.VITE_API_URL;
    const response = await fetch(`${apiUrl}getCSRFToken/`, {
        method: "GET",
        credentials: "include",
      });
    const data = await response.json();
    return data.csrfToken;
};

useEffect(() => {
    // Fetch CSRF token on component mount
    getCSRFToken().then((csrfToken) => {
        Cookies.set("csrftoken", csrfToken);  // Store the token in a cookie
    });
  }, []);

The get request ALWAYS works. And using editthiscookie I have verified that the cookie is also being saved.

Additionally, here is the submit function for the form:

const handleSubmit = async (e) => {
    e.preventDefault();

    // Prepare form data to send to Django
    const formDataToSend = new FormData();
    formDataToSend.append("fullName", formData.fullName);
    // etc

    // API URL for the Django backend
    const apiUrl = import.meta.env.VITE_API_URL;

    const csrfToken = Cookies.get("csrftoken");  // Get the CSRF token from the cookie

    await fetch(`${apiUrl}contributeRequest/requestform/`, {
      method: "POST",
      headers: {
        "X-CSRFToken": csrfToken,  // CSRF token from the cookie
      },
      body: formDataToSend,
      credentials: "include",
    })
      .then((response) => {
        if (!response.ok) {
          throw new Error('Network response was not ok');
        }
        return response.json();
      })
      .then((data) => {
        console.log("SUCCESS:", data);
        setSubmitMessage("Your form has been successfully submitted!");

      .catch((error) => {
        console.error("FAILED:", error);
        setSubmitMessage("There was an error submitting your form. Please try again.");
      });
  };

When I check the request headers upon submitting the form, X-CSRFToken is set as the cookie value.

and below are my relevant django settings:

CORS_ALLOWED_ORIGINS = [ env('FRONTEND_URL'), ]

CSRF_TRUSTED_ORIGINS = [ env('FRONTEND_URL'), ]

CORS_ALLOW_CREDENTIALS = True
CSRF_COOKIE_SAMESITE = 'None'
CSRF_COOKIE_HTTPONLY = False

// I have tried the following false and true, both yield the same result
CSRF_COOKIE_SECURE = True

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    # ... other middleware ...
]

If I could get some guidance as to how I can resolve this, that would be amazing.

Вернуться на верх