As a summary for my mistakes:
- Don't forget to set the request content type.
- Get the csrf value, either from
NB. The default cookie name is csrftoken
, but can be overriden by CSRF_COOKIE_NAME
setting.
- The DOM, if you can't access the cookie (you set CSRF_USE_SESSIONS or CSRF_COOKIE_HTTPONLY to True)
document.querySelector('[name=csrfmiddlewaretoken]').value;
- Set the request header, I'am using XMLHttpRequest
const Http = new XMLHttpRequest();
Http.setRequestHeader("X-CSRFToken", CSRF_VALUE);
Http.setRequestHeader("X_CSRFTOKEN", CSRF_VALUE);
The header name is managed by CSRF_HEADER_NAME
setting, which its default is HTTP_X_CSRFTOKEN
.
But: "The header name received from the server is normalized by converting all characters to uppercase, replacing any hyphens with underscores, and adding an 'HTTP_' prefix to the name" src.
So, If you set the HTTP_X_CSRFTOKEN
header, Django will convert it to HTTP_HTTP_X_CSRFTOKEN
which wis incorrect name and will raise CSRF missed
error.
Http.setRequestHeader("X-CSRFToken", csrftoken); // This worked
Http.setRequestHeader("X-CSRFTOKEN", csrftoken); // Also this
Http.setRequestHeader("HTTP-X-CSRFToken", csrftoken); // Not working
Http.setRequestHeader("HTTP_X_CSRFTOKEN", csrftoken); // Not Working
Http.setRequestHeader("X_CSRFTOKEN", csrftoken); // Not working !!
Don't use url in ajax that is different than that of the browser 127.0.0.1
& localhost
are not the same !!
No need to set data.append("csrfmiddlewaretoken", csrftoken);
in the request body, As I know.