Verifying requests
You can verify inbound requests from our webhooks using HMAC SHA256 verification. Once you've created a webhook you'll see a notice showing you the secret
value that you can use for for verifying requests from us. If you need to find the secret again at a later stage you can also find it on the edit page of the webhook.
How to verify
- Grab the
secret
value for the webhook shown in the UI once created. - Use the
secret
and incoming request body as inputs for your HMAC function using a SHA256 algorithm. - Compare the HMAC hash you've generated with the value in the
signature
header of the incoming request - If they match you can trust that the request is legitimate
Important Security Considerations
- Protect Your Secret Key: Never expose your secret key in client-side code or logs.
- Use Secure Comparisons: Always use timing-safe comparisons to prevent attackers from exploiting timing differences.
- Validate Incoming Data: Ensure that you handle exceptions and validate all incoming data to prevent security vulnerabilities.
Below is a simple Python example showing how you can compute the HMAC value of an incoming request and verify it.
import hashlib
import hmac
def verify_hmac(secret_key: str, request_body: str, signature_header: str) -> bool:
"""
Verifies the HMAC SHA256 signature of an incoming request.
Args:
secret_key (str): The secret key provided by the webhook UI.
request_body (str): The raw body of the incoming HTTP request.
signature_header (str): The value of the 'signature' header from the incoming request.
Returns:
bool: True if the signature is valid, False otherwise.
"""
encoded_key: bytes = secret_key.encode("utf-8")
encoded_body: bytes = request_body.encode("utf-8")
computed_signature: str = hmac.new(
key=encoded_key, msg=encoded_body, digestmod=hashlib.sha256
).hexdigest()
return hmac.compare_digest(computed_signature, signature_header)
def main() -> None:
secret_key: str = "64a2a90e-1359-4ff6-a89e-4ab448773654"
request_body: str = "Incoming request body data..."
signature_header: str = "Value of incoming request 'signature' header..."
if verify_hmac(secret_key, request_body, signature_header):
print("Signature is valid.")
else:
print("Signature is invalid.")
if __name__ == "__main__":
main()