I was trying Django JWT Auth and noticed that the URL responds well to one type of post but doesn't respond well to another, but i can figure out why.
Basically, if i use the cURL POST referred in the readme.md, everything goes accordingly to planned:
$ curl -X POST -H "Content-Type: application/json" -d '{"username":"admin","password":"abc123"}' http://localhost:8000/api-token-auth/
but if you i use another type of cURL POST with the same info, it doesn't work:
$ curl -d 'username=admin&password=abc123' http://localhost:8000/api-token-auth/
I know that the "Content-Type" is diferent, but shouldn't the request be accepted in the same manner, they are both well formed posts?
Curl's -d option actually sends the request like it's a web browser. My guess is that the URL you're testing against doesn't have a standard web form, so it can't actually process the request.
TL;DR Pretty sure Django JWT Auth doesn't support the application/x-www-form-urlencoded content type.
From curl manual:
-d --data
(HTTP) Sends the specified data in a POST request to the HTTP
server, in the same way that a browser does when a user has
filled in an HTML form and presses the submit button. This will
cause curl to pass the data to the server using the content-type
application/x-www-form-urlencoded. Compare to -F, --form.
Hope this helps!
Related
I have the following curl that successfully logs me into a website. It returns a 302 and a cookie:
curl \
--verbose \
--request POST \
--data '__EVENTTARGET=&body%3Ax%3AtxtLogin=kingkong%40mailinator.com&body%3Ax%3AbtnLogin=&crypted_pass=736015615f9e251692a6a4aa8a7baa14' \
"https://emma.maryland.gov/page.aspx/en/usr/login"
Unfortunately, I have to insert the real username & encrypted password of the account. otherwise this curl it won't work. However, this is a completely dummy account with NO private data in it. So please don't get mad at me.
I want to convert it to a Python3 code using requests.post(). So I made this code:
>>> requests.post(
... url='https://emma.maryland.gov/page.aspx/en/usr/login',
... data={
... '__EVENTTARGET': '',
... 'body:x:txtLogin': 'kingkong#mailinator.com',
... 'body:x:btnLogin': '',
... 'crypted_pass': '736015615f9e251692a6a4aa8a7baa14'
... }
... )
<Response [200]>
But the response I get from the Python3 code (200) doesn't match the response I get from the Curl (302). This means that the target server senses a difference between the two requests.
How can I convert the curl to Python3 that sends the exact same underlying HTTP request?
Your requests code is actually smarter than the cURL command.
HTTP 302 - is a redirect, cURL didn't follow it and gave you the first response it got. You can make cURL follow the redirect with -L: Is there a way to follow redirects with command line cURL?
The requests code followed the redirect and gave you the final response, which happened to be a HTTP 200.
Try your curl command with -L and see if you get HTTP 200 or not.
Alternatively, you can ask requests to not follow redirects with the allow_redirects=False option: Is there an easy way to request a URL in python and NOT follow redirects?
I am trying to submit a form on a Flask app using curl. Unfortunately, I keep running into the "CSRF token missing" error.
I tried:
curl -X POST --form csrf_token=token --form data=#file.txt --form submit=submit {url} -v
I used a csrf_token from the app while I had it open in a browser. I also looked at https://flask-wtf.readthedocs.org/en/latest/csrf.html and tried to set X-CSRFToken in the header but still got the same error. Any suggestions for what is the correct way to use curl to feed the token to the flask app?
The problem is that you just sending token and flask cannot get your session which lives in browser cookie. So if you wish to access your view via curl it's not enough to pass token value within POST request, you have to attach cookie to. You can write cookie to local file with command:
curl -c /path/to/cookiefile {url}
Then modify it and send POST request to your server with attached cookie and token:
curl -b /path/to/cookiefile -X POST --form csrf_token=token --form data=#file.txt --form submit=submit {url} -v
I hope I can explain myself. with out making an arse of myself.
I am trying to use python 3.4 to send a url to a sparkcore api.
I have managed to use curl direcly from the windows command line:-
curl https://api.spark.io/v1/devices/xxxxxxxxxxxxxxx/led -d access_token=yyyyyyyyyyyyyyyy -d params=l1,HIGH
All works fine. there is a space between the led and -d, but that is not a problem.
I have read that reting to do this within python using libcurl is a big pain and I saw lots of messaged about using Requests, so I though I would give it a go.
So I wrote a small routine:
import requests
r = requests.get('https://api.spark.io/v1/devices/xxxxxxxxxxxxxxxxxx/led -d access_token=yyyyyyyyyyyyyyyyy -d params=l1,HIGH')
print(r.url)
print(r)
I get as return:
<Response [400]>
When I examine the URL which actually got sent out the spaces in the URL are replaced with %20. This seems to be my actual problem, because the %20 being added by requests are confusing the server which fails
"code": 400,
"error": "invalid_request",
"error_description": "The access token was not found"
I have tried reading up on how to inpractice have the spaces with out having a %20 being added by the encoding, but I really could do with a pointer in the right direction.
Thanks
Liam
URLs cannot have spaces. The curl command you are using is actually making a request to the url https://api.spark.io/v1/devices/xxxxxxxxxxxxxxx/led with some command line arguments (using -d)
The curl man (manual) page says this about the -d command line argument
-d, --data
(HTTP) Sends the specified data in a POST request to the HTTP server, in the same way that a browser does when a user has filled in an HTML form and presses the submit button. This will cause curl to pass the data to the server using the content-type application/x-www-form-urlencoded. Compare to -F, --form.
-d, --data is the same as --data-ascii. To post data purely binary, you should instead use the --data-binary option. To URL-encode the value of a form field you may use --data-urlencode.
If any of these options is used more than once on the same command line, the data pieces specified will be merged together with a separating &-symbol. Thus, using '-d name=daniel -d skill=lousy' would generate a post chunk that looks like 'name=daniel&skill=lousy'.
If you start the data with the letter #, the rest should be a file name to read the data from, or - if you want curl to read the data from stdin. Multiple files can also be specified. Posting data from a file named 'foobar' would thus be done with --data #foobar. When --data is told to read from a file like that, carriage returns and newlines will be stripped out.
So that says -d is for sending data to the URL with the POST request using the content-type application/x-www-form-urlencoded
The requests documentation has a good example of how to do that using the requests library: http://docs.python-requests.org/en/latest/user/quickstart/#more-complicated-post-requests
So for your curl command, I think this should work
import requests
payload = {'access_token': 'yyyyyyyyyyyyyyyy', 'params': 'l1,HIGH'}
r = requests.post("https://api.spark.io/v1/devices/xxxxxxxxxxxxxxx/led", data=payload)
print(r.text)
I am working on a Django server that takes an integer from POST data. If I send the integer via GET there's no problems, but it gets dropped when sent via POST.
I run the server with:
./manage.py runserver 0.0.0.0:8000
and then generate the POST request with:
curl -X POST -H "Content-Type: application/json" -d '{"myInt":4}' "http://0.0.0.0:8000/myURL/"
I am using PDB in the view, and here is the result I am getting for the following commands:
request.method
> 'POST'
request.body
> '{"myInt":4}'
request.POST
> <QueryDict: {}>
I have used #csrf_exempt as a decorator for the view, just to make sure that isn't causing any problems.
Currently it is baffling me that request.POST does not contain myInt, is my POST request not well-formed?
Your post request is sending JSON not application/x-www-form-urlencoded
If you look at the django docs about HttpRequest.POST .
A dictionary-like object containing all given HTTP POST parameters, providing that the request contains form data. See the QueryDict documentation below. If you need to access raw or non-form data posted in the request, access this through the HttpRequest.body attribute instead.
You need to POST form encoded data. I didn't test this and haven't used curl in a while, but I believe the following should work.
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "myInt=4" "http://0.0.0.0:8000/myURL/"
I'm using django-oauth2-provider with rest-framework to provide authentication in my API.
My mobile app is going to connect to my REST API to retrieve some data. No third party apps are going to get involved in the process.
According to this, the grant type required for this use case would be the password grant. Since it's a bad idea to store the secret in the device, I need to access the token without it.
I tried to send a request without the secret:
curl -X POST -d "client_id=MY_CLIENT_ID&grant_type=password&username=user&password=pass" http://localhost:8000/oauth2/access_token/
But the response I get is:
{"error": "invalid_client"}
My question is whether it is possible to do this with django-oauth2-provider, and how to do it.
Set Authorization Grant Type as Resource owner password-based
Put WSGIPassAuthorization On at same place as WSGIScriptAlias
You need to create a client through django admin UI and replace "MY_CLIENT_ID" with the ID.
"Client type" of application should be "public"
Just to combine solutions. This is what worked for me. Follow through on the Getting Started guide. However, on creating the application, provide the following:
Name: A name of your choosing
Client Type: Public
Authorization Grant Type: Resource owner password-based
Then the request should be:
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=password&username=<username>&password=<password>&client_id=<client_id>" http://localhost:8000/o/token/
or, if JSON,
to settings.py add:
OAUTH2_PROVIDER = {
# expect request body Content Type application/json
'OAUTH2_BACKEND_CLASS': 'oauth2_provider.oauth2_backends.JSONOAuthLibCore'
}
curl -X POST \
http://localhost:8000/o/token/ \
-H 'Content-Type: application/json' \
-d '{
"grant_type": "password",
"client_id": "<client_id>",
"username": "<username>",
"password": "<password>"
}'
You should use password grant type. The following curl command works with django-oauth-toolkit. I believe it should work with any other oauth provider as well.
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'grant_type=password&username=user&password=pass&client_id=client_id' 'http://localhost:8000/o/token/'
Please see the following link for more info: https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified#password