Saltar al contenido principal

Seguridad de webhooks

Cada solicitud de webhook de ConsentForge incluye una firma HMAC-SHA256. Verifique esta firma antes de procesar el payload para asegurarse de que la solicitud es genuina y no ha sido manipulada.

Encabezados de solicitud

EncabezadoDescripción
X-ConsentForge-SignatureResumen hexadecimal HMAC-SHA256 de {timestamp}.{body}
X-ConsentForge-TimestampMarca de tiempo Unix (segundos) cuando se envió el evento
X-ConsentForge-Delivery-IDID único para esta entrega (use para idempotencia)

Algoritmo de verificación

  1. Lea X-ConsentForge-Timestamp del encabezado de la solicitud
  2. Lea X-ConsentForge-Signature del encabezado de la solicitud
  3. Construya la cadena de firma: {timestamp}.{raw_request_body}
  4. Calcule HMAC-SHA256 de la cadena de firma usando su secreto de webhook
  5. Compare (con seguridad de tiempo) con la firma recibida
  6. Rechace si la marca de tiempo tiene más de 5 minutos de antigüedad (protección contra repetición)

Ejemplos de código

function verifyConsentForgeWebhook(
string $rawBody,
string $signature,
string $timestamp,
string $secret
): bool {
// Reject if too old (5 minutes)
if (abs(time() - (int)$timestamp) > 300) {
return false;
}

$signingString = $timestamp . '.' . $rawBody;
$expected = hash_hmac('sha256', $signingString, $secret);

return hash_equals($expected, $signature);
}

// Usage in a Laravel controller:
$rawBody = $request->getContent();
$signature = $request->header('X-ConsentForge-Signature');
$timestamp = $request->header('X-ConsentForge-Timestamp');
$secret = config('services.consentforge.webhook_secret');

if (!verifyConsentForgeWebhook($rawBody, $signature, $timestamp, $secret)) {
return response('Unauthorized', 401);
}

$payload = $request->json()->all();

Idempotencia

Use X-ConsentForge-Delivery-ID para deduplicar entregas reintentadas. Almacene los IDs de entregas procesadas y omita los duplicados.

Rotación de secretos

Para rotar su secreto de webhook:

  1. Genere un nuevo secreto en el Panel (el secreto antiguo sigue activo durante 24h)
  2. Actualice su servidor para usar el nuevo secreto
  3. Después de 24h, el secreto antiguo se invalida