Skip to main content

Webhook signing

We sign each webhook call with a signature in the request header. This will allow a third party to verify that a request was sent by Host.

When a webhook is created for a client we auto-generate a secret key for each endpoint and we use that secret key to sign the request. The signature is added into the header of that request under the 'Host-Signature' attribute.

Lost your secret key?

Contact Host Building to be provided with your secret key, you will need to provide the region and endpoint being called.

Example request

This is an example of a signed request with headers. Please note in this example we have indented the data for display purposes, and that were are not currently displaying exactly how the request is formatting as it will not fit in one line.

POST https://127.0.0.1/events-webhook
Connection: close
Content-Length: 481
Content-Type: application/json
Host: webhook.site
Host-Signature: t=1645157641,signature=d4e962829fd4c119171aa18cf68f430e9019c70da6c3f219a2a6dbd057146569
{
"event": "event_booked",
"event_at": "2022-02-22T06:49:37+00:00",
"source": "localhost",
"data": {
"id": "7382",
"event_id": "836",
"event_name": "STEM Workshops for Home Schooled Students",
"event_image": "https://cdn.au-staging.host-building.com/data/2020/Jul/01/6b9345c1568c8a091bc6a3b0c5dd6f62---JJC---L-https-cdnevbuccom-images-102417088-56005389539-1-original.jpg",
"user": {
"id": "46990",
"name": "Kish Jeetun",
"email": "kish.jeetun@cbre.com"
},
"session_start": "2022-02-23 10:00:00",
"session_end": "2022-02-23 11:00:00",
"cost": "$0.00"
}
}

Validating a request

Signature from the headers above:
Host-Signature: t=1645512577,signature=d4e962829fd4c119171aa18cf68f430e9019c70da6c3f219a2a6dbd057146569

The signature is made up of two components:

  • a 't' component which is the timestamp when the request was signed;
  • a 'signature' component which is the hashed signature.

The signature was computed using Hash Message Authentication Code (HMAC) with SHA-256 algorithm.

Step 1. Get the signature from the request

Split the two components of the signature using the "," character, then separate each component on the "=" character to get the key and value pair. The value 't' refers to the timestamp and 'signature' to the hash signature.

Step 2. Create string to compute your own signature

Concatenate the following components to a single string:

  1. The timestamp
  2. The "." character
  3. The JSON payload as string, after squashing extra whitespace and new lines

Referring to the above request, you should have the following string

1645512577.{"event":"event_booked","event_at":"2022-02-22T06:49:37+00:00","source":"localhost","data":{"id":"7382","event_id":"836","event_name":"STEM Workshops for Home Schooled Students","event_image":"https:\/\/cdn.au-staging.host-building.com\/data\/2020\/Jul\/01\/6b9345c1568c8a091bc6a3b0c5dd6f62---JJC---L-https-cdnevbuccom-images-102417088-56005389539-1-original.jpg","user":{"id":"46990","name":"Kish Jeetun","email":"kish.jeetun@cbre.com"},"session_start":"2022-02-23 10:00:00","session_end":"2022-02-23 11:00:00","cost":"$0.00"}}

Step 3. Compute signature

Use your webhook secret key, to compute a HMAC with SHA256 hash and compare the signature in the request header matches your computed signature.

Comparing hashes

For most languages it is not recommended to use "==" or "===" when comparing HMAC hashes, instead use your language specific function for comparing hashes.

Code Examples

// Your Secret Key
$secretKey = 'b964e986-dc94-42e6-b24e-cb1ff2fd6fd4';

// Generate your own signature
$computedSignature = hash_hmac(
'sha256',
'1645512577.{"event":"event_booked","event_at":"2022-02-22T06:49:37+00:00","source":"localhost","data":{"id":"7382","event_id":"836","event_name":"STEM Workshops for Home Schooled Students","event_image":"https://cdn.au-staging.host-building.com/data/2020/Jul/01/6b9345c1568c8a091bc6a3b0c5dd6f62---JJC---L-https-cdnevbuccom-images-102417088-56005389539-1-original.jpg","user":{"id":"46990","name":"Kish Jeetun","email":"kish.jeetun@cbre.com"},"session_start":"2022-02-23 10:00:00","session_end":"2022-02-23 11:00:00","cost":"$0.00"}}',
$secretKey
);

// compare signature
if (hash_equals($computedSignature, 'd4e962829fd4c119171aa18cf68f430e9019c70da6c3f219a2a6dbd057146569')) {
echo "Signature is valid.";
exit;
}

echo "Signature is NOT valid";