Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use curl with Django, csrf tokens and POST requests

I'm using curl to test one of my Django forms. The calls I've tried (with errors from each, and over multiple lines for readability):

(1):

curl -d "{\"email\":\"[email protected]\"}" --header "X-CSRFToken: [triple checked value from the source code of a page I already loaded from my Django app]" --cookie "csrftoken=[same csrf value as above]" http://127.0.0.1:8083/registrations/register/ 

(with http header and csrftoken in cookie) results in a 400 error with no data returned.

(2):

curl -d "{a:1}" --header "X-CSRFToken:[as above]" --cookie "csrftoken=[as above];sessionid=[from header inspection in Chrome]" http://127.0.0.1:8083/registrations/register/ 

(as in (1) but no spaces in header property declaration, and with sessionid in cookie too) results in the same 400 error with no data returned.

(3):

curl -d "{a:1}" --header "X-CSRFToken:[as above]" http://127.0.0.1:8083/registrations/register/ 

(only http header with X-CSRFToken, no cookie) results in error code 403, with message: CSRF cookie not set.

How can I test my form with curl? What factors am I not considering besides cookie values and http headers?

like image 277
Trindaz Avatar asked May 16 '12 23:05

Trindaz


People also ask

What is curl Django?

With Django test curl, you can take your test cases and immediately try them against an actual server via the magic of copy-paste! Django's testing tools come with a great test client you can use to simulate requests against views.

Is CSRF token necessary Django?

Django has a {% csrf_token %} tag that is implemented to avoid malicious attacks. It generates a token on the server-side when rendering the page and makes sure to cross-check this token for any requests coming back in. If the incoming requests do not contain the token, they are not executed.


2 Answers

A mixture of Damien's response and your example number 2 worked for me. I used a simple login page to test, I expect that your registration view is similar. Damien's response almost works, but is missing the sessionid cookie.

I recommend a more robust approach. Rather than manually entering the cookies from other requests, try using curl's built in cookie management system to simulate a complete user interaction. That way, you reduce the chance of making an error:

$ curl -v -c cookies.txt -b cookies.txt host.com/registrations/register/ $ curl -v -c cookies.txt -b cookies.txt -d "[email protected]&a=1&csrfmiddlewaretoken=<token from cookies.txt>" host.com/registrations/register/ 

The first curl simulates the user first arriving at the page with a GET request, and all the necessary cookies are saved. The second curl simulates filling in the form fields and sending them as a POST. Note that you have to include the csrfmiddlewaretoken field in the POST data, as suggested by Damien.

like image 121
Kevin S. Avatar answered Sep 19 '22 18:09

Kevin S.


Try:

curl  -d "[email protected]&a=1"  http://127.0.0.1:8083/registrations/register/ 

Notice especially the format of the -d argument.

However, this probably won't work, as your view likely needs a POST request instead of a GET request. Since it will be modifying data, not just returning information.

CSRF protection is only required for 'unsafe' requests (POST, PUT, DELETE). It works by checking the 'csrftoken' cookie against either the 'csrfmiddlewaretoken' form field or the 'X-CSRFToken' http header.

So:

curl  -X POST  -d "[email protected]&a=1&csrfmiddlewaretoken={inserttoken}"  --cookie "csrftoken=[as above]"  http://127.0.0.1:8083/registrations/register/ 

It's also possible to use --header "X-CSRFToken: {token}" instead of including it in the form data.

like image 45
Damien Ayers Avatar answered Sep 17 '22 18:09

Damien Ayers