JAVASCRIPT
Verifying Webhook Signatures for Secure API Callbacks
Implement robust security for webhook endpoints by verifying request signatures, ensuring incoming data originates from trusted API providers.
const crypto = require('crypto');
function verifyWebhookSignature(payload, signatureHeader, secret) {
const hmac = crypto.createHmac('sha256', secret);
hmac.update(payload, 'utf8'); // Ensure payload is a string or Buffer
const expectedSignature = `sha256=${hmac.digest('hex')}`;
// Use a timing-safe string comparison to prevent timing attacks
return crypto.timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expectedSignature));
}
// Example usage in an Express.js route:
/*
const express = require('express');
const bodyParser = require('body-parser'); // For raw body access
const app = express();
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET || 'your_super_secret_key'; // Replace with your actual secret
// Use raw body parser for webhook endpoints BEFORE any other body parsers
app.use(bodyParser.raw({ type: 'application/json' })); // or other appropriate type for your webhook
app.post('/webhook', (req, res) => {
const signature = req.headers['x-hub-signature-256'] || req.headers['x-api-signature']; // Check common headers
if (!signature) {
return res.status(401).send('No signature provided.');
}
try {
const payload = req.body.toString('utf8'); // Get raw body as string
if (verifyWebhookSignature(payload, signature, WEBHOOK_SECRET)) {
const eventData = JSON.parse(payload); // Parse only after verification
console.log('Webhook verified and received:', eventData);
res.status(200).send('Webhook received successfully.');
} else {
res.status(403).send('Invalid signature.');
}
} catch (error) {
console.error('Error processing webhook:', error);
res.status(500).send('Internal Server Error.');
}
});
app.listen(3000, () => console.log('Webhook server listening on port 3000'));
*/
How it works: This Node.js snippet demonstrates how to verify webhook signatures using the `crypto` module. Webhooks often include a signature header (e.g., `X-Hub-Signature`) generated using a shared secret. By re-computing the HMAC signature from the raw request body and comparing it in a timing-safe manner, you can ensure that incoming webhook payloads are legitimate and have not been tampered with, crucial for securing API callbacks.