Saltar al contenido
meruma Desarrolladores

Desarrolladores · Webhooks

Verificar la firma

Cada aviso viene firmado con el secreto del webhook. Verifícalo antes de confiar en su contenido.

Los encabezados

Los avisos siguen Standard Webhooks: cualquier biblioteca de esa especificación los verifica con el secreto que te damos al crear el webhook.

  • webhook-id: el id del evento, igual en cada reintento. Sirve para no procesarlo dos veces.
  • webhook-timestamp: la hora del envío, en segundos. Descarta los avisos de más de 5 minutos.
  • webhook-signature: v1, seguido del HMAC-SHA256 en base64 de id.timestamp.cuerpo.

Verificar en Node, sin bibliotecas

const crypto = require('crypto');

const signed = `${headers['webhook-id']}.${headers['webhook-timestamp']}.${rawBody}`;
const key = Buffer.from(secret.replace(/^whsec_/, ''), 'base64');
const expected = crypto.createHmac('sha256', key).update(signed).digest('base64');
const valid = headers['webhook-signature']
  .split(' ')
  .some((part) => part === `v1,${expected}`);

Usa el cuerpo tal como llegó (rawBody), antes de convertirlo a JSON: cualquier cambio de espacios rompe la firma.

Verificar en Python

import base64, hashlib, hmac

signed = f"{h['webhook-id']}.{h['webhook-timestamp']}.".encode() + raw_body
key = base64.b64decode(secret.removeprefix("whsec_"))
expected = base64.b64encode(hmac.new(key, signed, hashlib.sha256).digest()).decode()
valid = any(part == f"v1,{expected}" for part in h["webhook-signature"].split())

Rotar el secreto

Desde Webhooks puedes rotar el secreto. El anterior sigue firmando 24 horas y el encabezado lleva las dos firmas, así tu sistema no se corta mientras lo actualizas.

Revisado el