117

Looking for some help with integrating a JSON API call into a Python program.

I am looking to integrate the following API into a Python .py program to allow it to be called and the response to be printed.

The API guidance states that a bearer token must be generated to allow calls to the API, which I have done successfully. However I am unsure of the syntax to include this token as bearer token authentication in Python API request.

I can successfully complete the above request using cURL with a token included. I have tried "urllib" and "requests" routes but to no avail.

Full API details: IBM X-Force Exchange API Documentation - IP Reputation

BSMP
  • 3,862
  • 8
  • 31
  • 41
user4657
  • 1,333
  • 2
  • 11
  • 9

4 Answers4

175

It just means it expects that as a key in your header data

import requests
endpoint = ".../api/ip"
data = {"ip": "1.1.2.3"}
headers = {"Authorization": "Bearer MYREALLYLONGTOKENIGOT"}

print(requests.post(endpoint, data=data, headers=headers).json())
Martin Thoma
  • 91,837
  • 114
  • 489
  • 768
Joran Beasley
  • 93,863
  • 11
  • 131
  • 160
  • The above throws the following syntax error: `Traceback (most recent call last): File "bearerreturn.py", line 6, in print requests.post(endpoint,data=data,headers=headers).json() TypeError: 'dict' object is not callable` Code Below: `import requests endpoint = "https://xforce-api.mybluemix.net:443/api/ip" data = {"ip":"1.1.2.3"} headers = {"Bearer token":"TOKEN WAS INSERTED HERE"} print requests.post(endpoint,data=data,headers=headers).json()` Any Ideas? – user4657 Apr 29 '15 at 20:41
  • you have an old version of requests ... `json` is a dict in your version and not a function `requests.post(...).json` ... dont call it – Joran Beasley Apr 29 '15 at 20:46
  • Thanks Joran Beasley. Updated Requests library via pip and this allowed me to keep original syntax. However now when I run the above it outputs this .json response: `{u'error': u'Not authorized. Access is only allowed via https://exchange.xforce.ibmcloud.com/#/'}` This is same as if I hit the URL directly in a browser. Am I missing something with token or the way endpoint is configured? Code: `import requests endpoint = "https://xforce-api.mybluemix.net:443/ipr/" data = {"ip":"1.1.2.3"} headers = {"Bearer token":"TOKEN_HERE"} print requests.post(endpoint,data=data,headers=headers).json()` – user4657 Apr 29 '15 at 21:34
  • unfortunately I cant really help with that... it is either a bad endpoint or your credentials are invalid (are you using their example token, that is only configured for their url?) or perhaps you need to put your app url in their deleoper panel for your code ... chances are thats your first token ... you need to exchange token for a refresh token that you can then use to get a more permanent token (at least thats how oauth2 usually works..) – Joran Beasley Apr 29 '15 at 21:38
  • whoops looks like i had the header wrong try the updated code – Joran Beasley Apr 29 '15 at 21:39
  • I am using a uniquely generated token that was generated via their guide: https://xforce-api.mybluemix.net:443/auth/anonymousToken – user4657 Apr 29 '15 at 21:40
  • well if i find myself with lots of free time ill give it a shot and see if i can get back to you ... can you give me a link to their guide? – Joran Beasley Apr 29 '15 at 21:43
  • Tried updated code: More success. Still throws following error though. `{u'error': u'Not found.'}` Code: `import requests endpoint = "https://xforce-api.mybluemix.net:443/ipr/" data = {"ip":"8.8.8.8"} headers = {"Authorization":"Bearer REALLY_LONG_TOKEN_HERE"} print requests.post(endpoint,data=data,headers=headers).json()` API Documentation Here: https://xforce-api.mybluemix.net/doc/#!/Authentication/auth_anonymousToken_get Thanks for your help so far! It really is much appreciated Joran. – user4657 Apr 29 '15 at 21:57
74

If you are using requests module, an alternative option is to write an auth class, as discussed in "New Forms of Authentication":

import requests

class BearerAuth(requests.auth.AuthBase):
    def __init__(self, token):
        self.token = token
    def __call__(self, r):
        r.headers["authorization"] = "Bearer " + self.token
        return r

and then can you send requests like this

response = requests.get('https://www.example.com/', auth=BearerAuth('3pVzwec1Gs1m'))

which allows you to use the same auth argument just like basic auth, and may help you in certain situations.

mmeister
  • 5
  • 3
Zhe
  • 952
  • 6
  • 9
  • This might be useful with zeep too. It uses requests.auth type of authorizations (for http headers auth, not soap headers) – smido Mar 04 '20 at 09:15
21

The token has to be placed in an Authorization header according to the following format:

Authorization: Bearer [Token_Value]

Code below:

import urllib2
import json

def get_auth_token():
    """
    get an auth token
    """
    req=urllib2.Request("https://xforce-api.mybluemix.net/auth/anonymousToken")
    response=urllib2.urlopen(req)
    html=response.read()
    json_obj=json.loads(html)
    token_string=json_obj["token"].encode("ascii","ignore")
    return token_string

def get_response_json_object(url, auth_token):
    """
    returns json object with info
    """
    auth_token=get_auth_token()
    req=urllib2.Request(url, None, {"Authorization": "Bearer %s" %auth_token})
    response=urllib2.urlopen(req)
    html=response.read()
    json_obj=json.loads(html)
    return json_obj
memu
  • 77
  • 12
DSG
  • 311
  • 1
  • 4
  • For Python3 : `req = urllib.request.Request(urlstr, None, {"Authorization": "Bearer %s" % enc_authstr}) response = urllib.request.urlopen(req)` – SidJ Jan 03 '20 at 05:28
8

Here is full example of implementation in cURL and in Python - for authorization and for making API calls

cURL

1. Authorization

You have received access data like this:

Username: johndoe

Password: zznAQOoWyj8uuAgq

Consumer Key: ggczWttBWlTjXCEtk3Yie_WJGEIa

Consumer Secret: uuzPjjJykiuuLfHkfgSdXLV98Ciga

Which you can call in cURL like this:

curl -k -d "grant_type=password&username=Username&password=Password" \

                    -H "Authorization: Basic Base64(consumer-key:consumer-secret)" \

                       https://somedomain.test.com/token

or for this case it would be:

curl -k -d "grant_type=password&username=johndoe&password=zznAQOoWyj8uuAgq" \

                    -H "Authorization: Basic zzRjettzNUJXbFRqWENuuGszWWllX1iiR0VJYTpRelBLZkp5a2l2V0xmSGtmZ1NkWExWzzhDaWdh" \

                      https://somedomain.test.com/token

Answer would be something like:

{
    "access_token": "zz8d62zz-56zz-34zz-9zzf-azze1b8057f8",
    "refresh_token": "zzazz4c3-zz2e-zz25-zz97-ezz6e219cbf6",
    "scope": "default",
    "token_type": "Bearer",
    "expires_in": 3600
}

2. Calling API

Here is how you call some API that uses authentication from above. Limit and offset are just examples of 2 parameters that API could implement. You need access_token from above inserted after "Bearer ".So here is how you call some API with authentication data from above:

curl -k -X GET "https://somedomain.test.com/api/Users/Year/2020/Workers?offset=1&limit=100" -H "accept: application/json" -H "Authorization: Bearer zz8d62zz-56zz-34zz-9zzf-azze1b8057f8"

Python

Same thing from above implemented in Python. I've put text in comments so code could be copy-pasted.

# Authorization data

import base64
import requests

username = 'johndoe'
password= 'zznAQOoWyj8uuAgq'
consumer_key = 'ggczWttBWlTjXCEtk3Yie_WJGEIa'
consumer_secret = 'uuzPjjJykiuuLfHkfgSdXLV98Ciga'
consumer_key_secret = consumer_key+":"+consumer_secret
consumer_key_secret_enc = base64.b64encode(consumer_key_secret.encode()).decode()

# Your decoded key will be something like:
#zzRjettzNUJXbFRqWENuuGszWWllX1iiR0VJYTpRelBLZkp5a2l2V0xmSGtmZ1NkWExWzzhDaWdh


headersAuth = {
    'Authorization': 'Basic '+ str(consumer_key_secret_enc),
}

data = {
  'grant_type': 'password',
  'username': username,
  'password': password
}

## Authentication request

response = requests.post('https://somedomain.test.com/token', headers=headersAuth, data=data, verify=True)
j = response.json()

# When you print that response you will get dictionary like this:

    {
        "access_token": "zz8d62zz-56zz-34zz-9zzf-azze1b8057f8",
        "refresh_token": "zzazz4c3-zz2e-zz25-zz97-ezz6e219cbf6",
        "scope": "default",
        "token_type": "Bearer",
        "expires_in": 3600
    }

# You have to use `access_token` in API calls explained bellow.
# You can get `access_token` with j['access_token'].


# Using authentication to make API calls   

## Define header for making API calls that will hold authentication data

headersAPI = {
    'accept': 'application/json',
    'Authorization': 'Bearer '+j['access_token'],
}

### Usage of parameters defined in your API
params = (
    ('offset', '0'),
    ('limit', '20'),
)

# Making sample API call with authentication and API parameters data

response = requests.get('https://somedomain.test.com/api/Users/Year/2020/Workers', headers=headersAPI, params=params, verify=True)
api_response = response.json()
Harvey
  • 6,913
  • 3
  • 52
  • 54