JAVASCRIPT
Secure Webhook Processing with Signature Verification (Node.js)
Ensure the integrity and authenticity of incoming webhook payloads by verifying request signatures using a shared secret, protecting against malicious spoofing.
const express = require('express');
const bodyParser = require('body-parser');
const crypto = require('crypto');
const app = express();
const WEBHOOK_SECRET = 'your-super-secret-key'; // Store this securely, e.g., in environment variables
// Use raw body parser for webhook requests as we need the raw body for signature verification
app.use(bodyParser.json({
verify: (req, res, buf) => {
// Store the raw body so we can access it later for verification
req.rawBody = buf.toString();
}
}));
app.post('/webhook', (req, res) => {
const signature = req.headers['x-hub-signature-256'] || req.headers['x-hub-signature']; // Example header
const payload = req.rawBody;
if (!signature) {
console.warn('Webhook received without signature.');
return res.status(401).send('Unauthorized: No signature provided.');
}
// Example for GitHub-style signature (HMAC SHA256)
// Format: 'sha256=<signature>'
const [algo, hash] = signature.split('=');
if (algo !== 'sha256') { // Or 'sha1' depending on the service
console.warn('Unsupported signature algorithm:', algo);
return res.status(400).send('Bad Request: Unsupported signature algorithm.');
}
const hmac = crypto.createHmac(algo, WEBHOOK_SECRET);
hmac.update(payload);
const digest = hmac.digest('hex');
if (crypto.timingSafeEqual(Buffer.from(digest), Buffer.from(hash))) {
console.log('Webhook signature verified successfully!');
// Process the webhook payload (req.body contains the parsed JSON)
console.log('Webhook payload:', req.body);
res.status(200).send('Webhook received and processed.');
} else {
console.error('Webhook signature verification failed!');
res.status(403).send('Forbidden: Invalid signature.');
}
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Webhook server listening on port ${PORT}`);
});
How it works: This Node.js Express snippet demonstrates how to verify incoming webhook requests using a shared secret. It uses `body-parser` to get the raw request body, which is essential for signature calculation. The `crypto` module then computes an HMAC hash of the payload using a secret key and compares it securely with the signature provided in the request headers, ensuring the webhook's authenticity and integrity.