Skip to main content

La petición

Cada entrega es un POST HTTPS con cuerpo JSON y estas cabeceras:
Cuerpo
El cuerpo es fino a propósito: dice qué cambió, no cómo. Lee el recurso actual por la API REST con tus propias credenciales — así además ves el último estado y no el que había al publicar.

Cómo se calcula la firma

  • secret es el valor whsec_… devuelto una vez por create o rotate-secret.
  • t es la hora Unix (segundos) en que el worker firmó la petición.
  • El cuerpo crudo es la secuencia exacta de bytes enviada; cualquier cambio de espacios u orden de claves invalida el digest.

Reglas de verificación

1

Lee el cuerpo crudo

Captura el cuerpo antes de que un middleware JSON lo parsee. Reserializar el objeto parseado cambia los bytes.
2

Parsea la cabecera

Espera exactamente t=<dígitos>,v1=<64 hex>. Rechaza cualquier otra cosa.
3

Comprueba la marca de tiempo

Rechaza cuando |ahora - t| > 300 segundos. Esto acota el replay de una petición capturada; mantén el reloj sincronizado (NTP).
4

Compara en tiempo constante

Recalcula el HMAC y compáralo con una función timing-safe.
5

Deduplica y confirma

Reintentos y replays reutilizan id. Registra los ids procesados, responde 2xx en menos de 10 segundos y haz el trabajo real de forma asíncrona.

Implementaciones de referencia

Node.js
Reflejan verifyOutboundWebhookSignature en backend/horizon-api/lib/webhook/outbound/webhook-signature.ts, que es lo que también usa el sink de pruebas integrado.

Respuesta

Detalles en Reintentos y fallos.
No pongas lógica de negocio antes de la verificación de firma. Un endpoint que parsea el cuerpo primero y verifica después es trivialmente suplantable.