Firecrawl firma todas las solicitudes de webhook mediante HMAC-SHA256. Verificar estas firmas garantiza que las solicitudes sean auténticas y no hayan sido manipuladas.
Tu secreto de webhook está disponible en la pestaña Advanced de la configuración de tu cuenta. Cada cuenta tiene un secreto único que se utiliza para firmar todas las solicitudes de webhook.
Mantén tu secreto de webhook seguro y nunca lo expongas públicamente. Si crees que tu secreto se ha visto comprometido, regénéralo de inmediato desde la configuración de tu cuenta.
Cada solicitud de webhook incluye un encabezado X-Firecrawl-Signature:
X-Firecrawl-Signature: sha256=abc123def456...
- Extrae la firma del encabezado
X-Firecrawl-Signature
- Obtén el cuerpo sin procesar de la solicitud (antes de analizarlo)
- Calcula el HMAC-SHA256 usando tu clave secreta
- Compara las firmas usando una función de comparación segura frente al tiempo
import crypto from 'crypto';
import express from 'express';
const app = express();
// Usa el analizador de cuerpo en bruto para verificar la firma
app.use('/webhook/firecrawl', express.raw({ type: 'application/json' }));
app.post('/webhook/firecrawl', (req, res) => {
const signature = req.get('X-Firecrawl-Signature');
const webhookSecret = process.env.FIRECRAWL_WEBHOOK_SECRET;
if (!signature || !webhookSecret) {
return res.status(401).send('No autorizado');
}
// Extrae el hash del encabezado de la firma
const [algorithm, hash] = signature.split('=');
if (algorithm !== 'sha256') {
return res.status(401).send('Algoritmo de firma no válido');
}
// Calcula la firma esperada
const expectedSignature = crypto
.createHmac('sha256', webhookSecret)
.update(req.body)
.digest('hex');
// Verifica la firma usando una comparación segura contra ataques de temporización
if (!crypto.timingSafeEqual(Buffer.from(hash, 'hex'), Buffer.from(expectedSignature, 'hex'))) {
return res.status(401).send('Firma no válida');
}
// Analiza y procesa el webhook verificado
const event = JSON.parse(req.body);
console.log('Webhook de Firecrawl verificado:', event);
res.status(200).send('ok');
});
app.listen(3000, () => console.log('Escuchando en el puerto 3000'));
Valida siempre las firmas
Nunca proceses un webhook sin verificar primero su firma:
app.post('/webhook', (req, res) => {
if (!verifySignature(req)) {
return res.status(401).send('No autorizado');
}
processWebhook(req.body);
res.status(200).send('OK');
});
Usa comparaciones seguras en tiempo constante
Las comparaciones de cadenas estándar pueden filtrar información por temporización. Usa crypto.timingSafeEqual() en Node.js o hmac.compare_digest() en Python.
Usa siempre un endpoint HTTPS para tu webhook para garantizar que los datos estén cifrados en tránsito.