Webhooks
Verificar y recibir
Cómo verificar la firma HMAC sobre el cuerpo crudo, deduplicar por event_id y responder sin perder eventos.
Solicitud que recibes
Trifaco envía un POST con JSON (esquema WebhookEvent, ejemplo) y estas cabeceras:
| Cabecera | Contenido |
|---|---|
X-Trifaco-Timestamp | Segundos Unix. |
X-Trifaco-Signature | v1= seguido del HMAC-SHA256 en hexadecimal. |
X-Trifaco-Key-Id | Identifica el secreto del receptor. |
X-Trifaco-Attempt-Id | Identifica este intento. |
Verificar la firma
- Clave: el texto del secreto tal como lo recibiste. No lo decodifiques de base64url.
- Mensaje: los bytes UTF-8 de
timestamp + ".", seguidos de los bytes exactos del cuerpo. - Verifica antes de parsear el JSON. No reconstruyas el JSON para firmarlo.
- Compara en tiempo constante.
- Acepta hasta 300 segundos de diferencia de reloj.
- Después de parsear, comprueba que
company_idyenvironmentson los esperados.
Misma lógica que usa el receptor de referencia (backend/modules/webhooks/crypto.ts):
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyWebhook(secret: string, timestamp: string, signature: string, body: Buffer) {
if (
!/^\d{1,12}$/.test(timestamp) ||
!/^v1=[0-9a-f]{64}$/.test(signature) ||
Math.abs(Date.now() / 1000 - Number(timestamp)) > 300
)
return false;
const expected =
'v1=' + createHmac('sha256', secret).update(`${timestamp}.`).update(body).digest('hex');
return timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}Durante una rotación, acepta el secreto nuevo y el anterior, eligiendo por X-Trifaco-Key-Id.
Recibir sin perder ni duplicar
- Guarda el evento de forma durable antes de responder
2xx. - Deduplica por
event_iden la misma transacción que aplica el efecto de negocio. Trifaco puede repetir un evento, por ejemplo si pierde tu respuesta. - Tolera el desorden.
resource_versiones la versión de la transición que originó el aviso, no necesariamente la última. Consulta el documento actual antes de actuar. - Separa recepción y proceso. Responder
2xxconfirma que guardaste el evento, no que tu negocio lo aplicó. Procesa la bandeja de forma independiente.
| Tu respuesta | Qué entiende Trifaco |
|---|---|
2xx | Recibido. |
| Cualquier otra, o sin respuesta | Reintentar (ver Reintentos y replay). |
Receptor de referencia
backend/examples/webhook-receiver.ts implementa todo lo anterior:
- rechaza con
401firmas inválidas o cuerpos alterados, y con403otra empresa o ambiente; - limita el cuerpo a 8 KiB (
413); - guarda el evento en una bandeja durable con deduplicación que sobrevive a reinicios, y solo entonces responde
204; - responde
503si no pudo guardar, para que Trifaco reintente.
Este comportamiento se verificó desde AWS: un 503 forzado seguido de un 204 en el reintento, un replay sin duplicar la bandeja, y firmas falsas o cuerpos alterados rechazados con 401 (resultado AG-001).