CSRF Tokens - dJango - REST API

Today I was stumped by... Django and CSRF Tokens. About a year and a half ago, my Python developer had mentioned something about Django having some form of cross site protection and some other modules. At that time he was graduating from uni and learning how to use python and Django. Something that went in passing because he could not explain the issue and he botched the deployment only to end up with removing some packages. The client did not have a need for some of the things so it passed and not much notice was given to Django and some of the quirks.
This morning, I was helping out an old client and the code was not working, it was a simple DataTask on a URLSession. The best part was it returned no error but the error was a 403 because the CSRF Token was missing or invalid. Never came across this error, generally you would get the data, response and error as the parameters on completion and then check if the error is nil and then check if the data is nil and/or check the statusCode on the response.

If you posted the data using Postman, or even cURL, it worked, but when you used swift, it failed. It would give a 403: CSRF Token was missing or Invalid.

This was a first, never encountered this one before, It was even more interesting because it worked with majority of the clients and software BUT failed on iOS using Swift, I think it also worked fine on the simulator which was strange.

So what is the real issue?

It came down to the fact that developers could have set the view to use session_authentication and/or cross site domain protection. So the request is returned with an error as it does not contain a CSRF Token. I believe that most of the other clients follow the return response that includes a set-cookie in the header, and based on that they set the cookie in the header and call the same end point again with the same data, this time it works fine. However because it is under the hood, you see it as one single command. Now, I have no way to ascertain that statement as I could not find evidence in cURL source code and many other are not exactly open source or written in languages I would not want to touch.

So ultimately we settled on a fix, that was if the call failed, we check for cookies and if the cookies contain a CSRF token, we set that into the header and call the same endpoint with the same data again and this time it works.

There was a post that mentioned that if someone using Alamofire faced this issue, they were advised to post the data by posting it in the URL than posting it with the data in the httpBody. I am not sure if that is how POST works, I thought that as a rule all post json data was encoded and included in the httpBody.

Setting a new header of type 'X-CSRFTOKEN' with the setting of the token value works and the other commands follow smoothly.

If you have any more experience with this and/or if you know why all other software like cURL, Postman, including writing code in C# works without having to set the header and get the data in one call vs Having to call twice in Swift or Objective-C.


Popular Posts