I am building an plugin for a certain application in c# which has to communicate with a Django rest interface. As you know, Django uses CSRF tokens for extra security.
I have a problem when doing a POST/PUT call to Django. The call will always return "CSRF Failed: CSRF token missing or incorrect.". I tested the call in the browser (The web interface can also edit data, and will call the same PUT request), and to my surprise a different csrf token value is used in the X-CSRFToken header, than the one stored in the cookie. Is the X-CSRFToken header supposed to use a newly generated token ? The X-CSRFToken value is never used again after this call (the old csrftoken value is still used for all subsequent calls...).
Obiously I have also read the Django docs regarding csrf tokens. Even though I think I understand how it works, I don't get why a new token is used for a POST/PUT. There are a lot of examples which do not make sense for use in my C# plugin.
What i do before doing the PUT:
- Fetch the CSRF token by requesting the login page which contains the csrfmiddlewaretoken in it's body.
- Store a cookie "csrftoken" with the token as value (The cookie is not stored automatically, unfortunately)
- Login the user (POST) using credentials (csrfmiddlewaretoken={token} is also passed as parameter)
After doing the above, all GET calls work perfectly. The problem occurs when i try to do a POST or PUT. This is my PUT code, ignoring the json and url generation since these are not the issue:
// The _csrftoken used here, is the one I fetch at the beginning
Client().DefaultRequestHeaders.Add("X-CSRFToken", _csrftoken);
// The content is json
var response = Client().PutAsync(url, content).GetAwaiter().GetResult();
// The returned content is: {"detail":"CSRF Failed: CSRF token missing or incorrect."}"
var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
// 403 is returned
if (response.IsSuccessStatusCode) { ... }
The above code is made with the following state:
- User is logged in (sessionid cookie is available)
- csrf token is available from login (csrftoken cookie is also available)
What I have tried to resolve the issue:
- Pass csrfmiddlewaretoken={token} as a parameter
- store a X-CSRFToken cookie
- Using the X-CSRFToken which i copied from a PUT done in the web interface
- Trying HttpWebRequest instead of PutAsync
- Replicate a PUT from the web interface by copying all the headers/parameters/cookies from a PUT done in the web interface
- ...
Can someone help me understand what I am doing wrong ?
Thank you very much for any help you can give me.