I have the need to POST a request to a service that requires a hash SHA256 signature for autentication. I have both "app_id" and "app_secret" used to generate the hash during the process.
I have tried to do it, but receiving an invalid signature from the service provider when trying to POST a request.
From the provider instructions, I need to:
1. Create a MAC string that will contain all request data. This should be the elements:
AppId + HTTP Method + URI + UNIX Timestamp + Nonce (unique string for each request) + base64 string from payload md5
2. Generate the SHA256 hash from the string in point 1, using the provided AppSecret. 3. The final authentication signature will be composed of the following elements:
[ApiKey AppId:hash:nonce:timestamp]
What I have done so far:
app_id = 'my_app_id'
app_secret = 'my_app_secret'
providerURL = 'https://the_provider_url'
#code for calling the POST method
def publish_data(number, date, status):
endPointUrl = providerURL + "/v1/posting"
#just for testing purposes
number = '123456789'
date = None #opcional
status = 'valid'
payload = "?number={}&date={}&status={}".format(str(number), str(date), str(status))
strHash = hmac_generator(endPointUrl, 'POST', payload)
request_headers = {'Authorization': "ApiKey " + strHash,
'Content-Type': 'application/x-www-form-urlencoded'
}
response = requests.post(endPointUrl, headers=request_headers)
print('RESPONSE:', response.text)
#code for generating the hash
def hmac_generator(uri, method, body=None):
timestamp = int(time.time())
nonce = str(uuid.uuid4())
content = ""
if body is not None:
body_md5 = hashlib.md5(body.encode('utf-8')).digest()
content = base64.b64encode(body_md5).decode('utf-8')
#Generate the based64 MAC
#AppId + HTTP Method + URI + UNIX Timestamp + Nonce + base64 string from payload md5
message = app_id + method + uri + str(timestamp) + nonce + content
message_bytes = message.encode('utf-8')
#Generate the SHA256 hash
signature = hmac.new(app_secret, msg=message_bytes, digestmod=hashlib.sha256).digest()
hashed = base64.b64encode(signature).decode('utf-8')
return "{}:{}:{}:{}".format(app_id, hashed, nonce, timestamp)
I believe it is something related to "payload" because when I try to use a GET method using the same approach, it is working fine.
Code below:
#This method does not use payload
def get_details(number):
number = 'an existing number'
strUrl = endPointUrl + "/getdetails/" + str(number)
strHash = self.hmac_generator(strUrl, 'GET', None)
request_headers = {
'Authorization': "ApiKey " + strHash,
'Content-Type': 'application/x-www-form-urlencoded'
}
response = requests.get(strUrl, headers=request_headers)
return response
Any help? Thanks in advance
I have tried to create some code as per the original question. When trying to POST, I am getting an "invalid signature" error. When I try to GET, everything runs fine.