Webhook security
Every webhook request includes an HMAC signature. Verify it before you trust the payload.
How the signature is built
Each request is signed so you can check that it came from us and that the body was not changed. The signature is an HMAC of a Unix timestamp and the JSON payload, using SHA256 and your client secret.
What goes into the signature
- Timestamp and payload: We combine a Unix timestamp with the JSON payload, so each request has its own input.
- SHA256: We hash that input with SHA256 and your client secret.
Verify a request
- Read the header: Take the timestamp (
t) and the signature (v1) from thex-zigned-request-signatureheader. - Build the input: Concatenate the timestamp and the JSON payload you received.
- Sign it: Compute an HMAC-SHA256 of that string with your client secret.
- Compare: If your signature matches
v1, the request is authentic.
Code sample: HMAC verification
Here's how you can implement HMAC signature verification in TypeScript:
verifyHmacSignature.ts
import crypto from 'crypto'
function parseHeader(header: string) {
const timestampMatch = header.match(/t=(\d+)/)
const signatureMatch = header.match(/v1=([a-f0-9]+)/)
const timestamp = timestampMatch[1]
const signature = signatureMatch[1]
return { timestamp, signature }
}
function verifyHmacSignature(header: string, received_payload: string, client_secret: string) {
const parsed_header = parseHeader(header)
const payload = `${parsed_header.timestamp}.${json_payload}`
const signature = crypto.createHmac('sha256', client_secret).update(payload).digest('hex')
return signatureFromHeader === parsed_header.signature
}
function verifyWebhookRequest(req: Request) {
const header = req.headers['x-zigned-request-signature']
const received_payload = JSON.stringify(req.body)
const client_secret = 'your_client_secret'
return verifyHmacSignature(header, received_payload, client_secret)
}
note
This is a simplfied example using Typescript. You probably want to add some error handling and logging to make your implementation more robust. We are keeping it brief here to focus on the verification process.
A few things to keep in mind
- Verify every request: If you skip verification, you cannot tell a real webhook from a fake one.
- Log timestamps: Use them to spot replay attacks.
- Protect the client secret: Store it like a password. It is what makes the signature yours.