This guide explains how to implement secure webhook signature verification in Node.js using Express. The verification process ensures that webhook payloads are authentic and haven't been tampered with during transmission.
Overview
When a webhook is sent, the payload is signed with a shared secret using HMAC-SHA256. The signature is included in the request headers. The receiving server must verify this signature before processing the webhook.
Implementation Steps
1. Set Up Environment
First, ensure you have the required dependencies:
npm install express body-parser
Create an environment variable for your webhook signature key:
WEBHOOK_SIGNATURE_KEY=your_signature_key_here
2. Configure Express Server
You'll need to use the raw body parser to access the original payload for signature verification:
import express from 'express';
import bodyParser from 'body-parser';
const app = express();
const rawBodyParser = bodyParser.raw({ type: 'application/json' });
3. Implement Signature Verification
Create a middleware function to verify the webhook signature:
import crypto from 'crypto';
function verifyWebhookSignature(req: any, res: any, next: any) {
const webhookSecret = process.env.WEBHOOK_SECRET;
const signature = req.headers['x-webhook-signature'];
if (!signature) {
return res.status(401).send('Missing webhook signature');
}
// Compute signature from raw payload
const computedSignature = crypto
.createHmac('sha256', webhookSecret)
.update(req.body)
.digest('hex');
// Constant-time comparison to prevent timing attacks
const isSignatureValid = crypto.timingSafeEqual(
Buffer.from(computedSignature),
Buffer.from(signature)
);
if (!isSignatureValid) {
return res.status(403).send('Invalid webhook signature');
}
// Attach parsed body to request
req.parsedPayload = JSON.parse(req.body);
next();
}
4. Create Webhook Endpoint
Set up your webhook endpoint using the verification middleware: