Seguridad y entrega de webhooks
Verifica las firmas de los webhooks, entiende el comportamiento de reintentos y diagnostica problemas de entrega.
Por qué es importante
La verificación de firmas prueba que los payloads son auténticos y no fueron modificados. Entender el comportamiento de reintentos y la desactivación automática te ayuda a construir integraciones robustas.
Verificación de firmas
Cada entrega se firma con el secreto de firma de tu endpoint usando HMAC-SHA256. La firma cubre la marca de tiempo y el cuerpo de la solicitud para prevenir ataques de repetición.
El contenido firmado es la marca de tiempo ISO 8601 y el cuerpo JSON unidos por un punto:
<timestamp>.<body>
Ruby
timestamp = request.headers["X-Webhook-Timestamp"]
signature = request.headers["X-Webhook-Signature"]
body = request.body.read
expected = OpenSSL::HMAC.hexdigest("SHA256", signing_secret, "#{timestamp}.#{body}")
if ActiveSupport::SecurityUtils.secure_compare(expected, signature)
# Signature is valid
else
head :unauthorized
end
Node.js
const crypto = require("crypto");
function verifySignature(signingSecret, timestamp, body, signature) {
const expected = crypto
.createHmac("sha256", signingSecret)
.update(`${timestamp}.${body}`)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}
Python
import hmac
import hashlib
def verify_signature(signing_secret, timestamp, body, signature):
expected = hmac.new(
signing_secret.encode(),
f"{timestamp}.{body}".encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
Prevención de ataques de repetición
Compara X-Webhook-Timestamp con la hora actual y rechaza las solicitudes con más de 5 minutos de antigüedad.
Rotación del secreto de firma
Haz clic en Rotate Secret en la página de detalle del webhook para generar un nuevo secreto de firma. El secreto anterior se invalida de inmediato.
Para rotar sin interrupciones:
- Despliega tu endpoint para que acepte firmas tanto del secreto anterior como del nuevo
- Rota el secreto en Kit
- Verifica que las entregas funcionen con el nuevo secreto
- Elimina el secreto anterior de tu endpoint
Entrega y reintentos
Kit intenta la entrega hasta 5 veces cuando tu endpoint es inaccesible o devuelve un error.
| Intento | Comportamiento |
|---|---|
| 1 | Inmediato |
| 2-5 | Tiempos de espera con crecimiento polinomial |
| Configuración | Valor |
|---|---|
| Timeout de conexión | 10 segundos |
| Timeout de lectura | 15 segundos |
Una respuesta 2xx marca la entrega como completada. Cualquier otro código de estado o un timeout la marca como con error y activa un reintento.
Desactivación automática
Después de 15 fallos de entrega consecutivos en cualquier evento, Kit desactiva el webhook automáticamente.
Cuando se desactiva:
- No se intentan más entregas
- El estado cambia a Disabled con una marca de tiempo
disabled_at
Haz clic en Resume para reactivarlo. Esto reinicia el contador de fallos y restaura el webhook a modo activo.
Registros de entrega
Cada endpoint de webhook tiene una pestaña Deliveries que muestra las 50 entregas más recientes. Cada entrada incluye:
| Campo | Descripción |
|---|---|
| Event | Tipo de evento que activó la entrega |
| Status | pending, in_progress, completed o errored |
| Attempts | Número de intentos de entrega |
| Request headers | Encabezados enviados con la solicitud |
| Response | Código de estado HTTP o mensaje de error |
| Timestamp | Cuándo se creó la entrega |
Estados de entrega
| Estado | Significado |
|---|---|
pending |
Creada, esperando ser enviada |
in_progress |
En proceso de entrega |
completed |
El endpoint devolvió una respuesta 2xx |
errored |
Se agotaron todos los reintentos o el endpoint devolvió un error |
Retención de datos
Los registros de entrega se conservan durante 30 días y luego se eliminan automáticamente. Almacena los payloads de tu lado si necesitas una retención más prolongada.
Requisitos de URL
- HTTPS obligatorio – Los endpoints HTTP son rechazados
- Solo IPs públicas – Las URLs que resuelven a direcciones privadas (localhost, 10.x.x.x, 192.168.x.x, etc.) están bloqueadas
- Las URLs se validan en el momento de la creación y antes de cada entrega
Diagnóstico de problemas
| Problema | Causa | Solución |
|---|---|---|
| Firma no coincide | Secreto de firma incorrecto o cuerpo modificado antes de la verificación | Verifica contra el cuerpo crudo de la solicitud con el secreto actual |
| Entregas con timeout | El endpoint tarda más de 15 segundos | Devuelve 200 de inmediato y procesa de forma asíncrona |
| Webhook desactivado automáticamente | 15 fallos consecutivos | Corrige tu endpoint y luego haz clic en Resume |
| URL rechazada | IP privada o URL HTTP | Usa una URL HTTPS que resuelva a una IP pública |
| Eventos no se disparan | Webhook pausado o tipo de evento no suscrito | Verifica el estado del webhook y los eventos suscritos |
Lista de verificación rápida
- Copia tu secreto de firma desde la página de detalle del webhook
- Implementa la verificación de firma HMAC-SHA256 en tu endpoint
- Rechaza las solicitudes con marcas de tiempo de más de 5 minutos
- Devuelve un código de estado
2xxen menos de 15 segundos - Maneja los reintentos de forma idempotente (puedes recibir el mismo evento más de una vez)
- Monitorea los registros de entrega en busca de errores
- Configura alertas para cuando un webhook sea desactivado automáticamente