Webhook Signatures

Use Webhook Signatures to verify webhook events are coming from HostedHooks

Each webhook event is sent with a header HTTP_HOSTEDHOOKS_SIGNATUREcontaining a signature and timestamp. These can be used together with your endpoint secret to compare signatures and confirm that the webhook event you are receiving came from HostedHooks.

Prevent Replay Attacks

Replay attacks are when an attacker intercepts a webhook message and resends it to the endpoint. We help mitigate this by adding a timestamp into the HTTP_HOSTEDHOOKS_SIGNATURE for you to compare with. We use this timestamp to sign the payload, so the attacker would not be able to change the timestamp without invalidating the payload signature as well. In the case where the payload signature is valid, but the timestamp is too old, you can choose to reject the webhook.

We generate a new timestamp and signature when webhook messages are sent to the subscriber's endpoint. In the case of retries (where a previous webhook attempt returned a non 200 response), we will generate a new timestamp and signature.

HostedHooks Signature Verification

HostedHooks webhook messages will be sent with a HTTP_HOSTEDHOOKS_SIGNATURE that contains both a payload signature s= and a timestamp t=.

t=1623436092,
s=7e526f3c14539d4d2856a1a2e8b1112c944cd466670041fe758fcc930d8cdf23

New lines have been added here to make it more readable, but the actual HTTP_HOSTEDHOOKS_SIGNATUREis on one line.

Step 1: Parse the timestamp and signatures from the header

Split the header using the , to get both the s and t values. Then use the = to split the keys from the value. The s value corresponds to the payload signature and the t value corresponds to the timestamp.

Step 2: Create the signed_payload

To create the signed payload you will want to concatenate the following values

  • The timestamp

  • the character .

  • The JSON payload received (request body)

Step 3: Generate the expected Signature

Generate an HMAC with the SHA256 hash function. The key for the hash function is your endpoints signing secret and the signed_payload string is the message.

Step 4: Compare the signatures

Compare the signature that you received in the header (Step 1) with the generated signature (Step 3). If those match, then calculate the difference between the current timestamp and the received timestamp (step 1) and determine if the difference is within an acceptable tolerance.

Use a constant time string comparison to compare the generated signature with the received signature. This will protect against timing attacks.

Last updated