Passa al contenuto principale

Sicurezza webhook

Ogni richiesta webhook da ConsentForge include una firma HMAC-SHA256. Verifica questa firma prima di elaborare il payload per assicurarti che la richiesta sia autentica e non sia stata manomessa.

Header della richiesta

HeaderDescrizione
X-ConsentForge-SignatureDigest hex HMAC-SHA256 di {timestamp}.{body}
X-ConsentForge-TimestampTimestamp Unix (secondi) quando l'evento è stato inviato
X-ConsentForge-Delivery-IDID univoco per questa consegna (usa per l'idempotenza)

Algoritmo di verifica

  1. Leggi X-ConsentForge-Timestamp dall'header della richiesta
  2. Leggi X-ConsentForge-Signature dall'header della richiesta
  3. Costruisci la stringa di firma: {timestamp}.{raw_request_body}
  4. Calcola HMAC-SHA256 della stringa di firma usando il tuo segreto webhook
  5. Confronta (timing-safe) con la firma ricevuta
  6. Rifiuta se il timestamp ha più di 5 minuti (protezione da replay)

Esempi di codice

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();

Idempotenza

Usa X-ConsentForge-Delivery-ID per deduplicare le consegne ritentate. Memorizza gli ID di consegna elaborati e salta i duplicati.

Rotazione del segreto

Per ruotare il tuo segreto webhook:

  1. Genera un nuovo segreto nel Dashboard (il vecchio segreto rimane attivo per 24h)
  2. Aggiorna il tuo server per usare il nuovo segreto
  3. Dopo 24h, il vecchio segreto viene invalidato