I have an API working just fine on one URL (it returns a nice 201 CREATED):
curl -d #scan.json -H "Content-Type: application/json" -u admin -i -v "https://vincentle.pythonanywhere.com/api/beacons/"
But when I try to perform the same request without the SSL:
curl -d #scan.json -H "Content-Type: application/json" -u admin -i -v "http://vincentle.pythonanywhere.com/api/beacons/"
I get a 301 Moved Permanently response.
I have tried two fixes:
I defined a URL without the trailing slash (after reading this post). This is not the solution, request with, or without slash will return 301.
I added a header "HTTP_X_FORWARDED_PROTO: https" in my request, as I have the line SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') in my settings. This isn't the solution either.
Any idea?
You need to look at where you are redirected to.
My bet, your configuration does redirect http to https in which case it's an administration issue unrelating to Django / Django REST framework.
Related
I am trying to delete a file (video) from Google Cloud Storage via the cloudstorage api but although the file exists I'm getting the following error:
cloudstorage.delete('/catchamove-video/products/6411421952770048.mp4')
*** NotFoundError: Expect status [204] from Google Storage. But got status 404.
Path: '/catchamove-video/products/6411421952770048.mp4'.
Request headers: None.
Response headers: {'transfer-encoding': 'chunked', 'date': 'Sun, 07 May 2017 12:31:47 GMT', 'server': 'Development/2.0'}.
Body: ''.
Extra info: None.
Both the bucket and file are present on the console.
I am facing the same problem: getting 404 when delete a folder via REST API.
After some tests, I figured out how delete folder of GCP storage -
Have to delete all files (objects) in the folder, files in sub-folders and sub-folders and folder. Be noticed that when deleting empty folder, you may still get "404 Not Found"(normally gets 204), just ignore it and the empty folder will be actually deleted.
Examples:
curl -I -X DELETE -H "Authorization: Bearer <author_code>" https://www.googleapis.com/storage/v1/b/<bucket_name>/o/folder%2Fsub-folder%2Ffile1
curl -I -X DELETE -H "Authorization: Bearer <author_code>" https://www.googleapis.com/storage/v1/b/<bucket_name>/o/folder%2Fsub-folder%2Ffile2
curl -I -X DELETE -H "Authorization: Bearer <author_code>" https://www.googleapis.com/storage/v1/b/<bucket_name>/o/folder%2Fsub-folder%2F #May get 204 or 404 response code
curl -I -X DELETE -H "Authorization: Bearer <author_code>" https://www.googleapis.com/storage/v1/b/<bucket_name>/o/folder%2F #May get 204 or 404 response code
NOTE: "%2F" in the URL is actually "/" character
I have created an endpoint localhost:8000/getauthtoken to generate the authentication token.
The curl command that i am using to get the authentication token is:
curl --request POST --url localhost:8000/getauthtoken --header 'content-type: application/json' --data '{"username":"admin", "password":"admin123"}'
But i am getting
{"password":["This field is required."],"username":["This field is required."]}
But in the command i am passing both username and password
As per the DRF documentation http://www.django-rest-framework.org/api-guide/authentication/ this is the correct way.
Use httpie (available on pypi)
Then follow this on terminal:
Http post your_ip:your_port/your_authresource/ username='' password=''
Or you can try that in Curl in right way:
curl -X POST http://localhost:8000/api-token-auth/ -d "password=aaaaa&username=user"
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?
Here is a fully coded answer. The idea of the solution is:
you have to first visit the login page with GET to get the cookies file generated,
then parse the CSRF token out of the cookies file
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.
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.
Actually #Paterino answer is correct but it will not work on every implementation of sed. Instead sed 's/^.*csrftoken\s*//') we can use sed 's/^.*csrftoken[[:blank:]]*//') which is more old fashioned. MacOSXs curl doesn't use escaping, so \n\t\s don't work at all.
To use the token with a get request, use
$CURL_BIN \
-H "$DJANGO_TOKEN" \
-X GET https://yourdjangowebsite.com/whatever/
I tried using -d with -X GET, however it resulted in weird socket behaviour on the server side (Heruko H18 errors).
I'm using Django 4.1.2 and trying the #Paterino method found a couple of changes to make it work (but i have not enogh reputation to comment so wrote another answer).
Firstly, if the generated cookies.txt file is empty you have to ensure than csrf cookie is generated. I achieved this using django.views.decorators.csrf.ensure_csrf_cookie in django.contrib.auth.views.LoginView
Now, after login cookies.txt changes, so you have to recalculate DJANGO_TOKEN variable in the same way:
DJANGO_TOKEN="csrfmiddlewaretoken=$(grep csrftoken $COOKIES | sed 's/^.*csrftoken\s*//')"
From here the method doesn't change.
the accepted answer, until now(2022-12-19), has 2 issues:
misses updating DJANGO_TOKEN after login (since a new csrftoken cookie is returned after login)
doesn't include an example with a POST request (moving the csrftoken to a header) where -d already contains some payload
here is my version dealing with both:
# user and password from `./manage.py createsuperuser`
YOUR_USER='user'
YOUR_PASS='pass'
COOKIES=cookies.txt
LOGIN_URL=http://localhost:8000/admin/login/
# stores csrftoken cookie on cookies.txt
curl -s -c $COOKIES $LOGIN_URL > /dev/null
TOKEN_VALUE="$(grep -oP '(?<=csrftoken[[:space:]]).*' cookies.txt)" # https://stackoverflow.com/a/10358949/3026886 https://stackoverflow.com/a/4233691/3026886
# logs in, updating csrftoken and adding sessionid cookies
curl -b $COOKIES -c $COOKIES -d "csrfmiddlewaretoken=$TOKEN_VALUE&username=$YOUR_USER&password=$YOUR_PASS" $LOGIN_URL
# updates var env with new cookie
TOKEN_VALUE="$(grep -oP '(?<=csrftoken[[:space:]]).*' cookies.txt)"
# here comes the real request
curl -s -X POST -b $COOKIES -d "{\"a\":1}" -H "X-CSRFToken: $TOKEN_VALUE" http://localhost:8000/yourViewReceivingJsonPayload/ > /dev/null
rm cookies.txt
I i am new to django-rest-auth and apis.
Its the first time i build a rest auth and i am not very familiar with Authorization headers and Content Types.
I am trying to understand why when i try to authenticate a user in /login/ with Basic Authorization like this:
curl -X POST -H "Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=" 'https://myurl.com/rest-auth/login/' --insecure
i got this error message:
{"password":["(This field is required"]}
When passing the username and password in the body like this:
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'username=myuser&password=mypassword' 'https://myurl.com/rest-auth/login/' --insecure
I got the key:
{"key":"b5c0f3a9c7b2fc2f58a74b25f816e2968c64712f"}
Why this is happening?
I also wonder why when trying the same in /user/ it didn't throw me any error and give me my user model serialized
curl -X GET -H "Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=" -H "Cache-Control: no-cache" 'https://myurl.com/rest-auth/user/' --insecure
The only difference i can understand is that in /login i am using POST and in /user/ is GET
Can anybody explain this to me?
Thanks for reading!
The '/auth/login/' endpoint is specifically for getting an authentication token to use with token authentication on the rest of the app. It doesn't itself support any authentication methods. The second curl command uses the correct method. the third curl command works because you are using an endpoint which does support Basic Authentication (you can could also use the token you got in the second call).
pls refer
Inet Mode Example (unprivileged user with AltAuth)
$ echo -e "GET http://localhost/slurm/v1/diag HTTP/1.1\r\nAccept: */*\r\n" |
slurmrestd -f etc/slurm.token.conf
● slurmrestd: operations_router: /slurm/v1/diag for pipe:[1052487]
● HTTP/1.1 200 OK
● Content-Length: 973
● {
● "parts_packedg": 1,
● "req_timeg": 1568051342,
● "req_time_startg": 1568050812,
● "server_thread_count": 3,
… JSON continues ...
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?
Here is a fully coded answer. The idea of the solution is:
you have to first visit the login page with GET to get the cookies file generated,
then parse the CSRF token out of the cookies file
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.
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.
Actually #Paterino answer is correct but it will not work on every implementation of sed. Instead sed 's/^.*csrftoken\s*//') we can use sed 's/^.*csrftoken[[:blank:]]*//') which is more old fashioned. MacOSXs curl doesn't use escaping, so \n\t\s don't work at all.
To use the token with a get request, use
$CURL_BIN \
-H "$DJANGO_TOKEN" \
-X GET https://yourdjangowebsite.com/whatever/
I tried using -d with -X GET, however it resulted in weird socket behaviour on the server side (Heruko H18 errors).
I'm using Django 4.1.2 and trying the #Paterino method found a couple of changes to make it work (but i have not enogh reputation to comment so wrote another answer).
Firstly, if the generated cookies.txt file is empty you have to ensure than csrf cookie is generated. I achieved this using django.views.decorators.csrf.ensure_csrf_cookie in django.contrib.auth.views.LoginView
Now, after login cookies.txt changes, so you have to recalculate DJANGO_TOKEN variable in the same way:
DJANGO_TOKEN="csrfmiddlewaretoken=$(grep csrftoken $COOKIES | sed 's/^.*csrftoken\s*//')"
From here the method doesn't change.
the accepted answer, until now(2022-12-19), has 2 issues:
misses updating DJANGO_TOKEN after login (since a new csrftoken cookie is returned after login)
doesn't include an example with a POST request (moving the csrftoken to a header) where -d already contains some payload
here is my version dealing with both:
# user and password from `./manage.py createsuperuser`
YOUR_USER='user'
YOUR_PASS='pass'
COOKIES=cookies.txt
LOGIN_URL=http://localhost:8000/admin/login/
# stores csrftoken cookie on cookies.txt
curl -s -c $COOKIES $LOGIN_URL > /dev/null
TOKEN_VALUE="$(grep -oP '(?<=csrftoken[[:space:]]).*' cookies.txt)" # https://stackoverflow.com/a/10358949/3026886 https://stackoverflow.com/a/4233691/3026886
# logs in, updating csrftoken and adding sessionid cookies
curl -b $COOKIES -c $COOKIES -d "csrfmiddlewaretoken=$TOKEN_VALUE&username=$YOUR_USER&password=$YOUR_PASS" $LOGIN_URL
# updates var env with new cookie
TOKEN_VALUE="$(grep -oP '(?<=csrftoken[[:space:]]).*' cookies.txt)"
# here comes the real request
curl -s -X POST -b $COOKIES -d "{\"a\":1}" -H "X-CSRFToken: $TOKEN_VALUE" http://localhost:8000/yourViewReceivingJsonPayload/ > /dev/null
rm cookies.txt