Trifaco API
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:

CabeceraContenido
X-Trifaco-TimestampSegundos Unix.
X-Trifaco-Signaturev1= seguido del HMAC-SHA256 en hexadecimal.
X-Trifaco-Key-IdIdentifica el secreto del receptor.
X-Trifaco-Attempt-IdIdentifica 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_id y environment son 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

  1. Guarda el evento de forma durable antes de responder 2xx.
  2. Deduplica por event_id en la misma transacción que aplica el efecto de negocio. Trifaco puede repetir un evento, por ejemplo si pierde tu respuesta.
  3. Tolera el desorden. resource_version es la versión de la transición que originó el aviso, no necesariamente la última. Consulta el documento actual antes de actuar.
  4. Separa recepción y proceso. Responder 2xx confirma que guardaste el evento, no que tu negocio lo aplicó. Procesa la bandeja de forma independiente.
Tu respuestaQué entiende Trifaco
2xxRecibido.
Cualquier otra, o sin respuestaReintentar (ver Reintentos y replay).

Receptor de referencia

backend/examples/webhook-receiver.ts implementa todo lo anterior:

  • rechaza con 401 firmas inválidas o cuerpos alterados, y con 403 otra 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 503 si 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).

En esta página