JAVASCRIPT
Securing Webhooks by Verifying Request Signatures
Implement robust security for your webhook endpoints by verifying the request signature using a shared secret, protecting against unauthorized or tampered payloads.
const crypto = require('crypto');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET || 'your_super_secret_key'; // Use environment variable!
// Middleware to parse raw body for signature verification
app.use(bodyParser.raw({ type: 'application/json' }));
app.post('/webhook', (req, res) => {
const signature = req.headers['x-webhook-signature']; // Or 'x-hub-signature', etc.
const payload = req.body.toString('utf8'); // Get raw body as string
if (!signature) {
return res.status(401).send('No signature header provided.');
}
// Calculate expected signature
const hmac = crypto.createHmac('sha256', WEBHOOK_SECRET);
hmac.update(payload);
const expectedSignature = `sha256=${hmac.digest('hex')}`;
if (crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature))) {
// Signature is valid! Process the webhook payload.
const event = JSON.parse(payload); // Parse the payload now
console.log('Webhook received and verified:', event.type);
res.status(200).send('Webhook received and processed.');
} else {
console.warn('Webhook signature verification failed!');
res.status(403).send('Invalid signature.');
}
});
// app.listen(3000, () => console.log('Webhook server listening on port 3000'));
How it works: This Node.js Express snippet demonstrates how to secure a webhook endpoint by verifying the request signature. It uses the `crypto` module to calculate an HMAC (Hash-based Message Authentication Code) of the raw request body using a shared secret key. This calculated signature is then compared with the signature provided in a special HTTP header (e.g., `X-Webhook-Signature`). If they match, the webhook request is deemed authentic and untampered; otherwise, it's rejected, protecting your application from malicious or spoofed payloads. Note the use of `bodyParser.raw` to get the raw body before parsing, which is essential for signature verification.