webhooks
Protección anti-replay
Cómo Spectra evita que un webhook capturado sea replayado contra tu cuenta.
La protección anti-replay sobre un webhook firmado para dos ataques:
- Un atacante que capturó una request válida no puede reenviarla para disparar la misma order otra vez.
- Un emisor mal comportado no puede reenviar mensajes viejos por accidente tras blips de red.
El mecanismo
Cada request lleva X-Spectra-Timestamp. El worker aplica:
- Ventana de frescura — 5 minutos por default. Requests con timestamps más viejos que ahora − 5 min se rechazan con 401.
- Caché de nonce — el worker cachea
(secret_id, timestamp, body_hash)durante la ventana de frescura. Una segunda request con los tres iguales se rechaza con 409 Conflict. La caché es solo en memoria (sin escritura a Postgres por request) así que es barata.
Juntas: una request capturada es replayable como mucho 5 minutos, y solo si el atacante gana una carrera contra tu entrega original.
Tunear la ventana
Perfil → Webhooks → secret → Advanced → Freshness window.
1 min → estricto; recomendado para redes de baja latencia
5 min → default
15 min → laxo; solo si tu emisor tiene lag impredecible
Bajar de 1 minuto es arriesgado — clock skew entre emisor y worker puede hacer que requests genuinas fallen freshness checks.
¿Y la idempotency?
Idempotency (client_id) y anti-replay resuelven problemas
distintos. Idempotency permite al mismo emisor reintentar de forma
segura. Anti-replay impide a un emisor distinto reusar una request
capturada. Usa ambas.
Síntomas de clock skew
Si ves requests legítimas rechazadas con timestamp out of range, el
reloj de tu emisor está derivando. Revisa NTP. El error incluye el
now-time del worker para que computes el delta.