0

I want to encode an API key to include in an authorisation header for an HTTP request. I have used the Postman app to verify what the authorisation header should be and have used it to successfully make the request in Postman and when translating the URL and header information into a urllib2 request.

However, when I use the base64 module to encode the API key, the resulting string differs slightly from the encoded string from Postman which causes authorisation to fail when making the request. The only difference between the two strings is the last character: the correctly encoded string (from Postman) ends with "ZTk6" whereas the Python encoded string ends with "ZTk=".

I understand from this post that Python pads the end of base64 encoded strings using "=", however, why would this result in a different encoded string? How can I get Python to output the encoded key that correctly authorises a request to the API?

The Python code I have used to encode the API string is:

import base64
api_key_base64 = base64.b64encode(api_key_string)
# Have also tried
api_key_base64 = base64.b64encode(bytes(api_key_string))
# And
api_key_base64 = api_key_string.encode("base64")

The unencoded API key string contains 32 alphanumeric characters.

As I'm ultimately wanting to use the encoded key in an authorisation header, if there is a method to directly add the API key string to an urllib2 request without needing to encode, I would be happy to use that instead.

System: Windows 7 Enterprise

Python: 2.7.13 (ArcGIS Desktop 10.5.1 installation)

Although I am currently using Python 2.7, an ideal solution would be compatible with 3.x too.

Edit:

I realised that the encoding should be performed on a string that includes two authorisation components separated by ":", even when only one component is used (i.e. an API key). Hence, encoding credentials for the header should be:

import base64
username = "<username>"
password = "<password>"
user_cred_encoded = base64.b64encode("{}:{}".format(username, password))
api_key_string = "<api_key>"
api_key_encoded = base64.b64encode("{}:".format(api_key_string))

Which gave me the encoded API key I was expecting.

bparker856
  • 49
  • 3

1 Answers1

0

When I decode both or your base64 ends of strings, I get:

>>> base64.decodebytes(b'ZTk6')
b'e9:'
>>> base64.decodebytes(b'ZTk=')
b'e9'

So I would expect that for the Python version you just skip the last ':' (or b'\x3a') byte. Would not the postman version end with 2 ':' ?

In that case, this could be enough:

api_key_encoded = base64.b64encode("{}::".format(api_key_string))
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252