LS,
For our hubspot integeration we make use of webhooks so see when properties change, for the authentication of requests being made from hubspot to our system we are going to use the `X-Hubspot-Signature` headers as explained in the documentation:
We use a python system and I was able to mimic hashing behaviour as used in the example. Because of this I wanted to start testing using `test subscriptions` in hubspot GUI.
What I did is setup a https://putsreq.com bucket to catch my test request and test if the my hashing method of the request results in the same hash als was in the header. Sadly this was not the case.
The core of my question is exactly how does hubspot hash the request before sending it? constructing it exactly like in the documentation does not yield the correct result, here I took the correct secret key, the test url and the request body as formated when using `Copy JSON` button.
Does anybody know what I might be doing wrong?
Below you can find a python code snippet I used to test this. Here the example from the documentation does work, but my test from hubspot itself does not.
from hashlib import sha256
def main():
# example request from documentation:
# https://developers.hubspot.com/docs/faq/validating-requests-from-hubspot
secret = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"
url = "https://www.example.com/webhook_uri"
body = '{"example_field":"example_value"}'
xsig = "9569219f8ba981ffa6f6f16aa0f48637d35d728c7e4d93d0d52efaa512af7900"
validate(secret, url, body, xsig)
# Test request made by hubspot from https://app.hubspot.com/developer/5153176/application/189009/webhooks
# The app is only used to debug this exact issue
secret = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy" # need to be replaced with secret from app 189009
# To see requests send here check https://putsreq.com/UKQCqLn1pKDbA1IBpt8S/inspect
url = "https://putsreq.com/UKQCqLn1pKDbA1IBpt8S"
# Direct paste from 'Copy JSON' option in the hubspot webhook overview.
# In our system this data is retreived from this get_data using the `as_text` flag.
# https://tedboy.github.io/flask/generated/generated/flask.Request.get_data.html
body = """[
{
"eventId": 1,
"subscriptionId": 104266,
"portalId": 5153176,
"occurredAt": 1550566240770,
"subscriptionType": "contact.propertyChange",
"attemptNumber": 0,
"objectId": 123,
"changeSource": "CRM",
"propertyName": "email",
"propertyValue": "sample-value",
"appId": 189009
}
]"""
# Signature taken from the X-Hubspot-Signature header in the request send to putsreq
xsig = "237092981e91b0b56714f7c72d42a59736fd99b45f7b22194e5bd84726837136"
validate(secret, url, body, xsig)
def validate(secret: str, url: str, body: str, xsig: str) -> bool:
"""
Compare the hash of the request with the given X-Hubspot-Signature
"""
# build the source of the hash and encode it into bytes so sha256 can hash it.
source_bytes = f"{secret}POST{url}{body}".encode("UTF-8")
local_hash = sha256(source_bytes).hexdigest()
eq = xsig == local_hash
print(
f"Local hash:\t{local_hash}\n"
f"Expected hash:\t{xsig}\n"
f"Equal:\t\t{eq}\n"
f"String before hashing:\n{source_bytes}\n"
)
return eq
if __name__ == "__main__":
main()