Question

I've been asked to deal with an external REST API (Zendesk's, in fact) whose credentials need to be formatted as {email}/token:{security_token} -- a single value rather than the usual username/password pair. I'm trying to use the Python requests module for this task, since it's Pythonic and doesn't hurt my brain too badly, but I'm not sure how to format the authentication credentials. The Zendesk documentation only gives access examples using curl, which I'm unfamiliar with.

Here's how I currently have requests.auth.AuthBase subclassed:

class ZDTokenAuth(requests.auth.AuthBase):
    def __init__(self,username,token):
        self.username = username
        self.token = token

    def __call__(self,r):
        auth_string = self.username + "/token:" + self.token
        auth_string = auth_string.encode('utf-8')
        r.headers['Authorization'] = base64.b64encode(auth_string)
        return r

I'm not sure that the various encodings are required, but that's how someone did it on github (https://github.com/skipjac/Zendesk-python-api/blob/master/zendesk-ticket-delete.py) so why not. I've tried it without the encoding too, of course - same result.

Here's the class and methods I'm using to test this:

class ZDStats(object):
    api_base = "https://mycompany.zendesk.com/api/v2/"

    def __init__(self,zd_auth):
        self.zd_auth = zd_auth # this is assumed to be a ZDTokenAuth object

    def testCredentials(self):
        zd_users_url = self.api_base + "users.json"
        zdreq = requests.get(zd_users_url, auth=self.zdauth)
        return zdreq

This is called with:

credentials = ZDTokenAuth(zd_username,zd_apitoken)
zd = ZDStats(credentials)
users = zd.testCredentials()
print(users.status_code)
print(users.text)

The status code I'm getting back is a 401, and the text is simply {"error":"Couldn't authenticate you."}. Clearly I'm doing something wrong here, but I don't think I know enough to know what it is I'm doing wrong, if that makes sense. Any ideas?

Was it helpful?

Solution

What you're missing is the auth type. Your Authorization header should be created like this:

r.headers['Authorization'] = b"Basic " + base64.b64encode(auth_string)

You can also achieve the same passing by a tuple as auth parameter with:

requests.get(url, auth=(username+"/token", token))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top