Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cURL an Authenticated Django App?

I've a few APIs I'd like to test with cURL. I tried doing a GET as follows:

curl --user username:password --request GET http://my_domain/get_result/52d6428f3ea9a008358ad2d8/

On the server, it showed a '302' (which means redirection, right?). I'm guessing it redirected to the 'login/' page.

What is the proper way of getting this done?

Edit: I tried:

curl -c cookies.txt -b cookies.txt -L -d @login_form.txt http://my_domain/login/

where login_form.txt contains "username=username&password=password&this_is_the_login_form=1". Doesn't work. No cookies.txt files generated. And no login happening. Can you tell me how you achieve login to Django using cURL?

like image 978
Sreejith Ramakrishnan Avatar asked Jan 23 '14 11:01

Sreejith Ramakrishnan


People also ask

How do you pass authentication in curl?

To send basic auth credentials with Curl, use the "-u login: password" command-line option. Curl automatically converts the login: password pair into a Base64-encoded string and adds the "Authorization: Basic [token]" header to the request.

How does authenticate work in Django?

The Django authentication system handles both authentication and authorization. Briefly, authentication verifies a user is who they claim to be, and authorization determines what an authenticated user is allowed to do. Here the term authentication is used to refer to both tasks.

Does Django have authentication?

Django provides an authentication and authorization ("permission") system, built on top of the session framework discussed in the previous tutorial, that allows you to verify user credentials and define what actions each user is allowed to perform.


2 Answers

Here is a fully coded answer. The idea of the solution is:

  1. you have to first visit the login page with GET to get the cookies file generated,
  2. then parse the CSRF token out of the cookies file
  3. and do the login using a POST request, passing the data with -d.

Afterwards you can perform any request always using that CSRF token in the data ($DJANGO_TOKEN) or with a custom X-CSRFToken header. To log out simply delete the cookies file.

Note that you need a referer (-e) to make Django's CSRF checks happy.

LOGIN_URL=https://yourdjangowebsite.com/login/
YOUR_USER='username'
YOUR_PASS='password'
COOKIES=cookies.txt
CURL_BIN="curl -s -c $COOKIES -b $COOKIES -e $LOGIN_URL"

echo -n "Django Auth: get csrftoken ..."
$CURL_BIN $LOGIN_URL > /dev/null
DJANGO_TOKEN="csrfmiddlewaretoken=$(grep csrftoken $COOKIES | sed 's/^.*csrftoken\s*//')"

echo -n " perform login ..."
$CURL_BIN \
    -d "$DJANGO_TOKEN&username=$YOUR_USER&password=$YOUR_PASS" \
    -X POST $LOGIN_URL

echo -n " do something while logged in ..."
$CURL_BIN \
    -d "$DJANGO_TOKEN&..." \
    -X POST https://yourdjangowebsite.com/whatever/

echo " logout"
rm $COOKIES

I have a slightly more secure version of this code, which uses a file for submitting the POST data, as a Gist on GitHub: django-csrftoken-login-demo.bash

Interesting background reading on Django's CSRF token is on docs.djangoproject.com.

like image 193
Peterino Avatar answered Oct 01 '22 21:10

Peterino


Passing username:password in a curl request is only good for HTTP Authentication, which isn't how most websites do auth these days. Instead, you'll have to post to the login page, get the cookie, then pass it back when requesting your desired page.

like image 22
Daniel Roseman Avatar answered Oct 01 '22 20:10

Daniel Roseman