Webhooks Security
Learn about our available webhooks protection mechanisms that you can utilise for extra security.
Although Webhooks are a form of server to server communication and typically more resistant to tampering attempts, it’s still the best practice to introduce security measures to validate their authenticity.
We offer multiple different methods that can be introduced as an additional layer of security.
HTTP Authentication
Webhooks can be setup with a username and a password using Basic HTTP Authentication. See the main Webhooks guide for more detail.
Header Signature
Enterprise only
Webhook header signatures are available only on the Enterprise plan.
Each Webhook request contains a special FPJS-Event-Signature
HTTP header that is available as an additional validation measure. We strongly suggest adopting this method instead of Basic HTTP Authentication as it doesn't require sharing any kind of sensitive data (username/password).
The header signature is computed from the HTTP body of the webhook along with a symmetric key (a secret) generated during the webhook creation. HMAC with SHA-256 hash function is used the signature method.
Since the secret remains unique to a specific webhook, it's impossible to spoof invalid data without it.
FPJS-Event-Signature
Header Structure
FPJS-Event-Signature
Header StructureThe value of the FPJS-Event-Signature
header is a comma-separated list of <signatureversion>=<hash>
where the signatureversion
is the version of the signature and hash
is the computed signature hash.
Currently, the only supported version is v1
and the algorithm for v1
is a HMAC SHA-256 of the HTTP raw payload, using the webhook's secret. The secret is generated for each Webhook during its creation (see Setup below).
Setup
1. Get the Key from the Dashboard
When a webhook is created, we assign a unique symmetric key to it and display it once during the creation process. Save this secret for subsequent usage on your backend so that you can compute your HMAC and validate the webhook from the signature.
2. Verify Signature
The HMAC signature we assign to the FPJS-Event-Signature
header is calculated from the raw HTTP payload of the request. An example validation code might look like this
import * as crypto from "crypto";
import { Buffer } from 'buffer';
const checkSignature = (signature: string, data: Buffer, secret: string) => {
return signature === crypto.createHmac('sha256', secret).update(data).digest('hex');
}
const checkHeader = (header: string, data: Buffer, secret: string) => {
const signatures = header.split(',');
for (const signature of signatures) {
const [version, hash] = signature.split('=');
if (version === 'v1') {
if (checkSignature(hash, data, secret)) {
return true;
}
}
}
return false
}
//valid (allow)
console.log(checkHeader('v1=89e14bbd118da7945e4547c1b9f32fff890dc141a7162df45c1ccb7546a80b58', Buffer.from('payload'), 'secret'))
//invalid (reject)
console.log(checkHeader('v0=89e14bbd118da7945e4547c1b9f32fff890dc141a7162df45c1ccb7546a80b58', Buffer.from('payload'), 'wrongsecret'))
console.log(checkHeader('v1=79e14bbd118da7945e4547c1b9f32fff890dc141a7162df45c1ccb7546a80b58', Buffer.from('payload'), 'wrongsecret'))
Key Rotation
To rotate the webhook key, create another Webhook with the same URL and a distinctive name. Once you rotate the key on the backend and start ingesting the new signature, you can delete the old webhook completely to prevent duplicated information.
Updated 28 days ago