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.