const crypto = require('crypto');
function verifyWebhookSignature(req, secret) {
const signature = req.headers['x-conductor-signature'];
const timestamp = req.headers['x-conductor-timestamp'];
const body = JSON.stringify(req.body);
// Prevent replay attacks
const currentTime = Math.floor(Date.now() / 1000);
if (Math.abs(currentTime - parseInt(timestamp)) > 300) {
throw new Error('Webhook timestamp too old');
}
// Compute expected signature
const payload = `${timestamp}.${body}`;
const expectedSignature = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
// Compare signatures
if (!crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
)) {
throw new Error('Invalid webhook signature');
}
return true;
}
// Express middleware
app.post('/webhooks/conductor', (req, res) => {
try {
verifyWebhookSignature(req, process.env.WEBHOOK_SECRET);
// Process webhook
const { event, data } = req.body;
console.log(`Received ${event}:`, data);
res.status(200).json({ received: true });
} catch (error) {
console.error('Webhook verification failed:', error);
res.status(401).json({ error: error.message });
}
});