Webhook signatures
About webhook signatures
All webhooks that Monite sends to your endpoints include a Monite-Signature
header. You can verify the signature included in this header to ensure that the received webhooks were actually sent by Monite and haven’t been tampered in transit.
The Monite-Signature
header contains a Unix timestamp and a signature, separated by a comma. The timestamp is prefixed by t=
, and the signature is prefixed by v1=
. For example:
Monite generates signatures using a hash-based message authentication code (HMAC) with SHA-256, and using a secret key that only you and Monite know.
All API calls mentioned in this guide require a partner access token.
Get the signature secret
Monite generates a unique signing secret for each webhook subscription. If you create multiple subscription for the same event, these subscriptions will have different secrets. The secrets in the production and sandbox environments are also different.
The secret is returned to you when you initially create a webhook subscription by calling POST /webhook_subscriptions
:
Note down the secret
from the response, as this is the only time you see it.
Regenerate a secret
For improved security, we recommend that you generate a new signing secret periodically. You can also regenerate the secret if you suspect it has been compromised.
To generate a new secret for a webhook subscription, call POST /webhook_subscriptions/{webhook_subscription_id}/regenerate_secret
. The subscription ID can be retrieved, for example, from the webhook_subscription_id
field in the webhook events that you receive from Monite.
The old secret expires immediately, and a new secret is returned in the response:
New webhooks triggered by this subscription from now on will be signed using the new secret.
How to verify webhook signatures
To verify a webhook’s signature, use the secret key to generate your own signature for the given webhook payload. Follow these steps:
1. Extract the timestamp and signature from the header
Split the Monite-Signature
header value by the ,
character to get a list of elements. Next, split each element by the =
character to get key-value pairs.
The timestamp is the value of the t
key, and the signature is the value of the v1
key. You can ignore any other keys.
2. Verify the timestamp (Recommended)
To prevent replay attacks, we recommend that you check the signature timestamp t
against the current time and reject webhooks whose timestamp is too far off in the past or future from the current time. The acceptable time difference can be, for example, 5 minutes or less.
This requires that your server’s time be synchronized using NTP or other means.
3. Calculate the expected signature
Concatenate the value of the t
timestamp with the character .
and the contents of the webhook’s raw request body. For example:
Next, calculate the HMAC signature of the resulting string using the SHA-256 hash function and the signing secret of your Monite webhook subscription.
This gives you the expected signature for the specified timestamp and webhook event payload.
4. Compare the signatures
Compare your calculated expected signature with the actual signature (v1
value) extracted from the webhook’s Monite-Signature
header.
If the signatures match, the webhook can be considered a legitimate Monite webhook. If the signatures do not match, the webhook should be rejected.
Example
Below is sample Python code that demonstrates how to verify Monite webhook signatures. The default acceptable time difference is 5 minutes (300 seconds). Error handling is omitted for simplicity.