JAVASCRIPT
Securely Processing Webhook Payloads in Node.js
Learn how to set up an Express.js endpoint to receive and securely verify webhook payloads from third-party services using HMAC signatures for integrity.
// Install: npm install express body-parser crypto
const express = require('express');
const bodyParser = require('body-parser');
const crypto = require('crypto');
const app = express();
const WEBHOOK_SECRET = 'your_super_secret_webhook_key'; // Replace with a strong, unique secret
// Raw body parser for signature verification
app.use(bodyParser.json({
verify: (req, res, buf) => {
req.rawBody = buf; // Store raw body for signature verification
}
}));
app.post('/webhook-endpoint', (req, res) => {
const signature = req.headers['x-hub-signature-256'] || req.headers['x-signature']; // Example header names
if (!signature) {
console.error('Webhook received without signature');
return res.status(401).send('Unauthorized: Signature missing');
}
// Calculate HMAC-SHA256 signature
const hmac = crypto.createHmac('sha256', WEBHOOK_SECRET)
.update(req.rawBody)
.digest('hex');
// Compare the calculated signature with the one from the header
const receivedSignature = signature.replace('sha256=', ''); // Remove prefix if present
if (!crypto.timingSafeEqual(Buffer.from(hmac, 'hex'), Buffer.from(receivedSignature, 'hex'))) {
console.error('Webhook signature mismatch:', { expected: hmac, received: receivedSignature });
return res.status(403).send('Forbidden: Invalid signature');
}
// Signature is valid, process the webhook payload
console.log('Webhook payload received and verified:', req.body);
// Example: Respond to the webhook sender
res.status(200).send('Webhook received successfully');
// Add your business logic here, e.g., update a database, trigger another service
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Webhook server listening on port ${PORT}`);
});
How it works: This Node.js snippet demonstrates how to create an Express.js endpoint to receive and validate webhooks. Many services send webhooks with a signature (HMAC) in the request header, allowing you to verify that the payload genuinely originated from the service and hasn't been tampered with. The code uses `body-parser` to get the raw request body, then calculates an HMAC-SHA256 signature using a shared secret and compares it with the one provided in the `x-hub-signature-256` header, ensuring message integrity and authenticity before processing the data.