For each event delivery, Bridge will include a webhook signature header in the HTTP request for event authenticity verification
- The header name is
X-Webhook-Signature ;
- The header value format is
t=<timestamp>,v0=<base64 encoded signature> , where the timestamp is in milliseconds;
To verify the signature, follow these steps:
- Parse the signature header to extract the
timestamp and base64 encoded signature;
- Join
timestamp with the raw http request body data with a dot (.), and generate a SHA256 digest of that string;
- Perform a strict base64 decoding on the
base64 encoded signature to get the decoded signature;
- Verify the signature using the per-endpoint
public key, the decoded signature (from Step 3), and the digest (from Step 2) as the message to verify.
Bridge hashes the payload twiceThe signature is over SHA256(SHA256("<timestamp>.<raw body>")). Node crypto.verify, Python cryptography, Ruby OpenSSL, and Java Signature all hash the message you hand them, so pass them the Step 2 digest rather than the raw "<timestamp>.<raw body>" string — passing the raw string hashes the payload only once and verification always fails. Go’s rsa.VerifyPKCS1v15 does not hash its input at all, so it needs the Step 2 digest hashed a second time before verifying. Working samples for every language are in the setup guide linked below.
To avoid replay attacksBridge advises the receiving endpoint to disregard events that are older than a few minutes, e.g. 10 minutes, and return a 400 status to request retries. For each event delivery retry, Bridge generates a new timestamp.
Check out the guide here to see sample code setting up webhooks.