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 la solicitud

EncabezadoDescripción
X-ConsentForge-SignatureDigesto 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 (seguro contra temporización) 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 {
// Rechazar si es demasiado antigua (5 minutos)
if (abs(time() - (int)$timestamp) > 300) {
return false;
}

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

return hash_equals($expected, $signature);
}

// Uso en un controlador Laravel:
$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 anterior sigue activo durante 24 horas)
  2. Actualice su servidor para usar el nuevo secreto
  3. Después de 24 horas, el secreto anterior queda invalidado