Can't do post with curl and ApiKeyAuthentication in tastypie - python

I am using tastyPie 0.9.11 to create a RESTful API.
I got the API working ok, but then when I added APIKeyAuthentication I couldn't get the POST request to work.
I have set authentication/authorization in my resource meta as:
authentication = ApiKeyAuthentication()
authorization= Authorization()
and I have manually added an API key in the admin site for user admin, with key 1234567890.
When I do a GET it works ok (http://127.0.0.1:8000/api/v1/application/?format=json&username=admin&api_key=1234567890 )
However when I try to do a POST using curl:
curl --dump-header - -H "Authorization: ApiKey admin:1234567890" -H "Content-Type: application/json" -X POST --data '{"user": "/api/v1/user/1/", "title":"api test application"}' http://localhost:8000/api/v1/application/
I get a 401 not authorized error.
I am following the documentation by adding the Authorization header, but maybe there is something else I am doing wrong?

Specifying the ApiKey via header was added after v0.9.11. It will be in the v0.9.12 release.

Related

Receive Indeed API Access Token [Python]

I am trying to get the Indeed vacanties of my company via API with python. I am following https://developer.indeed.com/docs/authorization/3-legged-oauth and https://mathiashaentjens.medium.com/how-do-you-extract-data-using-the-indeed-api-and-build-your-own-indeed-campaign-reporting-8127252ef073.
I create Indeed API keys and recevive the Authorization Code. But i couldnt get Access Token. I send the same POST as documents via curl and python requests but i got this error;
{'error_description': 'Your request might include sensitive information passed in the URL query string. Parameters must be passed in the HTTP request body using the application/x-www-form-urlencoded format (See https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3). For increased security, we recommend that you periodically rotate your application secret at https://secure.indeed.com/account/apikeys.', 'error': 'invalid_request'}
My python code is like;
headers = {'content-type': 'application/x-www-form-urlencoded','accept':'application/json'}
payload = {'code':'XXXX', 'client_id':'XXXX', 'client_secret':'XXXX', 'redirect_uri': 'http://localhost', 'grant_type':'authorization_code'}
response = requests.post('https://apis.indeed.com/oauth/v2/tokens', params=urllib.parse.urlencode(payload), headers=headers)
response.json()
and via command line;
curl -X POST -H "Content-Length: 0" -H "Content-Type: application/x-www-form-urlencoded" -H "Accept: application/json" "https://apis.indeed.com/oauth/v2/tokens?code=XXXX&client_id=XXXX&client_secret=XXXX&redirect_uri=http://localhost&grant_type=authorization_code"
Is there anyone familiar with this error?

How to exchange authorization code for access token Twitter API?

I am developing an app that will read some tweets stats of my company. I want to let all the employees to connect with their twitter accounts.
I am facing the following problem: I am stuck at the "Exchange authorization code for access token".
The response url after Authorize is: https://example/v1/browser-callback?state=state&code=all0UTY5TVVMYmctNjZEQVpYYYYYYYYZZZZZXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
I suppose I have to change the code all0UTY5TVVMYmctNjZEQVpYYYYYYYYZZZZZXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX for access_token and access_token_secret, but I did not find how to do that on the documentation that twitter offers to us.
You need first to know the type of flow you are trying to implement
First you need to know what is the grant type of your client_id in the twitter side, i see in the callback there is code that means you are in normal authorization code or Authorization Code Flow with Proof Key for Code (PKCE), to know that check in your first call to twitter if you see in the params code_challenge and code_challenge_method if yes It's PKCE flow;
Second, I see that you have successfully done the first step of flow, then if you are in the PKCE, you need in your callback to send another request to get a final token like this:
client_id=your client_id&
code_verifier=the code generated by the application in the first step&
redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fcallback&
grant_type=authorization_code&
code=the code sent from twitter
I'm not sure what the docs looked like back in March, but to do this now you simply need to build the request headers with the code argument from the redirect URL. From the example url you gave (https://example/v1/browser-callback), your code is:
all0UTY5TVVMYmctNjZEQVpYYYYYYYYZZZZZXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
And the curl request you would make for a private client to retrieve the user's bearer and refresh token would be:
curl --location --request POST 'https://api.twitter.com/2/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic YOUR_BASE64_ENCODED_ClientID:ClientSecret_HERE'\
--data-urlencode 'code=all0UTY5TVVMYmctNjZEQVpYYYYYYYYZZZZZXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'redirect_uri=https://example/v1/browser-callback' \
--data-urlencode 'code_verifier=challenge'
where YOUR_BASE64_ENCODED_ClientID:ClientSecret_HERE is (per the docs):
To create the basic authorization header you will need to base64 encoding on your Client ID and Client Secret which can be obtained from your App’s “Keys and Tokens” page inside of the developer portal.
You'll need to make this request to get the initial bearer token/refresh token for private clients within 30 seconds of receiving the code at your callback URL after the user has authorized your app.

Does PayPal still support activity report and balance via HTTP REST API?

thanks for reading - my questions are simple:
What am I doing wrong?
What am I missing?
Do I need to additional access to make use of the report engine?
I cannot seem to obtain balance or transaction data from my pp account using a simple python client despite what appears to be correct use of documented APIs.
I have:
a business account
dev portal access
valid creds for a Sandbox and Live API use
My py client wraps a few API calls and successfully completes the following:
obtain API token using dev portal creds
use API token to make valid HTTP requests to the balances and transactions API resources
API responses indicate 200 OK
However, except for the OAuth token request, all of the responses all say Empty XML data
Pseudo-sample code
# -- pp_auth_header is a global, contains Auth Bearer token
def get_balances():
print("get_balances...")
headers = pp_auth_header
endpoint = "/v1/reporting/balances"
query = "?currency_code=USD&as_of_time=2021-02-22T00:00:00-0700"
r = requests.get(pp_report_eng_url + endpoint + query, headers=pp_auth_header)
print("get_balances - status: {}".format(r.status_code))
if r.status_code == 200:
print("get_balances - r.text: {}".format(r.text))
# -- output of the above is
get_balances...
get_balances - url: https://api-m.sandbox.paypal.com/v1/reporting/balances?currency_code=USD&as_of_time=2021-02-22T00:00:00-0700
get_balances - status: 200
get_balances - r.text: Empty XML data
Generate an acess_token and then test from the command line with curl, as documented:
curl -v -X GET
https://api-m.sandbox.paypal.com/v1/reporting/balances?currency_code=USD&as_of_time=2016-10-15T06:07:00-0700
\
-H "Content-Type: application/json" \
-H "Authorization: Bearer Access-Token"
Ensure you pass the headers described there, including "Content-Type: application/json".
PayPal REST APIs do not return XML.
If this doesn't work, post the output of that curl -v command as well as the scopes returned by the oauth2 token request. Update your question with those details.

How to send data on a curl redirect?

I have an API which is currently on HTTP, I moved the API using SSLify library in python flask.
Now when I send data using curl request
curl -v -k -H "Content-Type: application/json" -X POST \
--data '{"title":"foobar","body": "This body"}' \
-L http://X.Y.Z.W.us-west-2.compute.amazonaws.com/test
It returns an empty string to me by using request.data
If I make the request to begin with https it returns correct value. If there is a redirect how can I send data ?
SSLify issues a 301 or 302 redirect status code depending on your configuration. So you need to pass --post301 or --post302 to curl.
The reason for this can be found in the curl man page:
When curl follows a redirect and the request is not a plain GET (for
example POST or PUT), it will do the following request with a GET
if the HTTP response was 301, 302, or 303. If the response code was
any other 3xx code, curl will re-send the following request using
the same unmodified method.
You can tell curl to not change the non-GET request method to GET
after a 30x response by using the dedicated options for that: --post301, --post302 and -post303.

compare python requests with curl

I am interfacing with an API using requests and requests_oauthlib.
I successfully authenticate and access all the GET methods of the API, but get error 500 with POST methods. For example:
r = oauth.post("https://api.timelyapp.com/1.0/1/clients",
data={"client":{"name":"newclient", "color":"c697c0" }},
allow_redirects=False, headers={"Content-Type": "application/json"})
The issue is that I tested the same exact call with curl and it works correctly, here the curl code:
curl -v -X POST -H "Content-Type: application/json" -H "Authorization: Bearer XXXXXXXXXXXX" --data '{"client": { "name": "newclient", "color":"c697c0" }}' "https://api.timelyapp.com/1.0/1/clients"
how can I dig deeper in requests to compare its call with curl?
UPDATE:
Also, noticed that if I do not specify content type:
r = oauth.post("https://api.timelyapp.com/1.0/1/clients",
data={"client":{"name":"newclient", "color":"c697c0" }},
allow_redirects=True)
I get instead a 302 with redirection to the site homepage, where I fetch the content of the page. In any case the new client is not added.
You might want to try this instead:
data=json.dumps(payload)
From python-requests doc:
There are many times that you want to send data that is not
form-encoded. If you pass in a string instead of a dict, that data
will be posted directly.

Categories

Resources