Allcoin signed POST request fails - python

The API i am using requires an MD5 encryption to work on POST requests. I am trying the make an 'userBalance' request to the API using the documentation https://www.allcoin.ca/api_market/market But every time it gives me back {'code': 1, 'msg': '签名校验失败'} (which means signature check failed). The API only asks for 2 parameteres, the api_key and sign. I carefully follow the guidance of the documentation, but the API still rejects the POST. Any suggestions why it fails the signature check? Am i missing something?
import hashlib
import keys
import requests
KEY = keys.allcoin["key"]
API_SECRET = keys.allcoin["secret"]
msg = "api_key='{}&secret_key={}".format(KEY, API_SECRET)
signature = hashlib.md5(msg.encode("utf-8")).hexdigest()
parameters = {
"api_key": KEY,
"sign": signature.upper(),
}
params = "&".join("{}={}".format(a, b) for a, b in parameters.items())
url = "http://www.allcoin.ca/Api_User/userBalance"
r = requests.post(
headers={
"Content-Type": "application/x-www-form-urlencoded",
'user-agent': 'my-app/0.0.1'
},
url=url,
params=parameters
)
print(r.json())

I think you want to change params=parameters to params=params in your requests.post().

Related

Http Basic Auth with RFC2045-MIME variant of Base64 in python

I am currently working with and API that requires "RFC2045-MIME variant of Base64, except not limited to 76 char/line" this seems to be different from the normal basic auth used in the requests library. Curious if anyone else has come across this and been able to solve it? I imagine I will have to write a function to do this encoding and build the header manually.
Yes, you can create a function as shown below where the headers for the request are created manually.
For this implementation, you will need these variables:
API_PUBLIC_KEY,
API_SECRET_KEY,
host_url,
endpoint (where the API is supposed to hit).
import base64
import requests
def create_request():
auth_header = base64.b64encode(bytes(f'{API_PUBLIC_KEY}:{API_SECRET_KEY}'.encode('ascii'))).decode('utf-8')
headers = {
'Host': host_url,
'Authorization': f'Basic {auth_header}',
'Content-Type': 'application/json'
}
api_endpoint = f'https://{host_url}/{endpoint}'
data = {}
response = requests.request("POST", api_endpoint, headers=headers, data=data)
print(response.text.encode('utf8'))

Unable to retrieve the api token using requests library python

I'm trying to use requests API to login into Zabbix API, but unable to do due to the below issue.
I want to achieve the login by pyzabbix module, but I want to use API user authentication token.
Without password and username in the code (any suggestion would help me).
Error:
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Code:
import requests
from pprint import pprint
import json
url = 'http://127.0.0.1/zabbix'
########################################
# user.login
########################################
payload = {
"jsonrpc" : "2.0",
"method" : "user.login",
"params": {
'user': 'Admin',
'password':'Zabbix',
},
"auth" : None,
"id" : 0,
}
headers = {
'content-type': 'application/json',
}
res = requests.post(url, data=json.dumps(payload), headers=headers)
print(res)
res = res.json()
print('user.login response: ',res['result'])
If you want to call the Zabbix API you have to use the correct endpoint, which is api_jsonrpc.php.
So, for instance you can use:
url = 'http://127.0.0.1/api_jsonrpc.php'
However your code does not account for errors (ie: if Admin/Zabbix is wrong, your script will return a key error, because the error response does not contain a result.
A better choice is to use a library such as py-zabbix

Consuming API with graphql queries throwing 401 error on R but working fine on Python

I have a requirement to access some information through an API. I need to do this on R. I tried doing on Python and it worked just fine but facing 401 error while doing the same operation on R.
I have the API key and also know the query to be performed. I have attached both Python and R code below.
Python:
import requests
headers = {
'Content-Type': 'application/json',
'Authorization': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX',
}
query = """
{
boards (ids: 157244624) {
permissions
}
}
"""
response = requests.get('https://XYZwebsite.com/', headers=headers, json={'query': query})
R:
require(httr)
headers = c(
`Content-Type` = 'application/json',
`Authorization` = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX'
)
data = '{
boards (ids: 157244624) {
permissions
}
}'
res <- GET(url = 'https://XYZwebsite.com/', add_headers(.headers=headers), body = data)
Am i missing out something in the R code? It looks pretty much the same but i am getting a 401 error on R for some weird reason.
In my case api key was expired... really long journey let me to:
amplify update api
walk through all
choose api key
enter new api key name
enter 365 days no further changes
amplify push will not detect changes, so use amplify push --force
maybe it helps
Perhaps try:
r <- GET("https://XYZwebsite.com/",
add_headers(`Content-Type` = "application/json",
`Authorization` = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX"),
body = data)
Edit:
With the gist you are working off of:
Authenticate first:
token <- GQL(auth_query)$authenticate$jwtToken
Then you can run your queries by passing the token you get in the response:
GQL(current_person_query, .token = token)
Seems like you are trying to do two things at once.
If you already have the token then it looks like you are passing it incorrectly:
auth_header <- paste("bearer", .token)
res <- POST(.url, body = pbody, encode="json", add_headers(Authorization=auth_header), ...)
As it should be passed as "bearer XXXXXXXXXXXXXXXXX".

Connect R to an API, pass it username and password

I have been trying to retrieve data from an API using R, but haven't succeeded yet. I tried doing it in R using the httr package and the GET function, but I get the following error when I enter the URL:
Error: 'new_handle' is not an exported object from 'namespace:curl'
What it comes down to is that I want to connect to data and that I have to pass some arguments like password and username.
I do have some Python code from a colleague that works (I have anonymized the URLs that are specific to our company), what I want is to connect to the data in a similar way in R:
------------- Equivalent Python code: --------------
import urllib
import datetime as dt
import dateutil
import json
headers = {u'content-type': u'application/x-www-form-urlencoded; charset=UTF-8'}
values = {"grant_type": "password",
"username": "XXXXXXXXX",
"password": "XXXXXXXXX",
"client_id": "PS"}
ko = urllib.request.Request("XXXXXX",
urllib.parse.urlencode(values).encode("utf-8"),
headers)
token = urllib.request.urlopen(ko).read()
epic = token.decode()
token_key = epic.split(",")[0].split(":")[1].replace('"', "")
lines_to_write = list()
lines_to_write.append("Identifier;Year;Period;Park Energy Availability [%]")
start_day = dt.datetime(2015, 1, 1)
data_day = start_day
headers = {u'content-type': u'application/json', u'Authorization': 'Bearer ' + token_key}
values = {'scope': {}, 'period': {'Begin': str(data_day).replace(" ", "T"), 'End': str(data_day + dateutil.relativedelta.relativedelta(months=1)).replace(" ", "T")}}
hest = urllib.request.Request("XXXXXXXXX", json.dumps(values).encode(), headers)
data = urllib.request.urlopen(hest)
vild_hest = data.read()
Any help would be greatly appreciated,
Best regards,
Tristan
The R code for API you presented will not work since it is just simply fractions of what is needed. Below you find the structure that R needs for working towards a REST API. The username and password will be passed to API server through the body of the POST (either as stated below or it could also be added as a list in the body).
You will also have to provide a key (in below case "API-KEY"). Note that you are sending a POST to initiate the authentication with the API server. Most API server will send you back 1 or 2 keys that you will use in later communication with the API server.
It is correct that all http interaction will take help of the package httr.
GET will be used in later stage in the communication between your API client and API server but not during the first authentication phase.
POST (
url = "xxx",
add_headers(
"API-KEY" = "xxx",
"VERSION" = "2",
"Content-Type" = "application/json; charset=UTF-8",
"Accept" = "application/json; charset=UTF-8"),
body = "{identifier: xxx, password: xxx}"
)

Python request with authentication (access_token)

I am trying to use an API query in Python. From the command line I can use curl like so:
curl --header "Authorization:access_token myToken" https://website.example/id
This gives some JSON output. myToken is a hexadecimal variable that remains constant throughout.
I would like to make this call from python so that I can loop through different ids and analyze the output. Before authentication was needed I had done that with urllib2. I have also taken a look at the requests module but couldn't figure out how to authenticate with it.
The requests package has a very nice API for HTTP requests, adding a custom header works like this (source: official docs):
>>> import requests
>>> response = requests.get(
... 'https://website.example/id', headers={'Authorization': 'access_token myToken'})
If you don't want to use an external dependency, the same thing using urllib2 of the standard library looks like this (source: the missing manual):
>>> import urllib2
>>> response = urllib2.urlopen(
... urllib2.Request('https://website.example/id', headers={'Authorization': 'access_token myToken'})
I had the same problem when trying to use a token with Github.
The only syntax that has worked for me with Python 3 is:
import requests
myToken = '<token>'
myUrl = '<website>'
head = {'Authorization': 'token {}'.format(myToken)}
response = requests.get(myUrl, headers=head)
>>> import requests
>>> response = requests.get('https://website.com/id', headers={'Authorization': 'access_token myToken'})
If the above doesnt work , try this:
>>> import requests
>>> response = requests.get('https://api.buildkite.com/v2/organizations/orgName/pipelines/pipelineName/builds/1230', headers={ 'Authorization': 'Bearer <your_token>' })
>>> print response.json()
import requests
BASE_URL = 'http://localhost:8080/v3/getPlan'
token = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImR"
headers = {'Authorization': "Bearer {}".format(token)}
auth_response = requests.get(BASE_URL, headers=headers)
print(auth_response.json())
Output :
{
"plans": [
{
"field": false,
"description": "plan 12",
"enabled": true
}
]
}
A lot of good answers already, but I didn't see this option yet:
If you're using requests, you could also specify a custom authentication class, similar to HTTPBasicAuth. For example:
from requests.auth import AuthBase
class TokenAuth(AuthBase):
def __init__(self, token, auth_scheme='Bearer'):
self.token = token
self.auth_scheme = auth_scheme
def __call__(self, request):
request.headers['Authorization'] = f'{self.auth_scheme} {self.token}'
return request
This could be used as follows (using the custom auth_scheme from the example):
response = requests.get(
url='https://example.com',
auth=TokenAuth(token='abcde', auth_scheme='access_token'),
)
This may look like a more complicated way to set the Request.headers attribute, but it can be advantageous if you want to support multiple types of authentication. Note this allows us to use the auth argument instead of the headers argument.
Have you tried the uncurl package (https://github.com/spulec/uncurl)? You can install it via pip, pip install uncurl. Your curl request returns:
>>> uncurl "curl --header \"Authorization:access_token myToken\" https://website.com/id"
requests.get("https://website.com/id",
headers={
"Authorization": "access_token myToken"
},
cookies={},
)
I'll add a bit hint: it seems what you pass as the key value of a header depends on your authorization type, in my case that was PRIVATE-TOKEN
header = {'PRIVATE-TOKEN': 'my_token'}
response = requests.get(myUrl, headers=header)
One of the option used in python to retrieve below:
import requests
token="abcd" < retrieved based>
headers = {'Authorization': "Bearer {}".format(token)}
response = requests.get(
'https://<url api>',
headers=headers,
verify="root ca certificate"
)
print(response.content)
If you get hostname mismatch error then additional SANs need to be configured in the server with the hostnames.
Hope this helps.

Categories

Resources