Verifica firma HMAC

Autenticità e integrità dei webhook in ingresso

Visualizza come Markdown

Ogni webhook inviato da Userbot è firmato con HMAC-SHA256 per garantire due cose: che la richiesta provenga davvero da Userbot (autenticità) e che il payload non sia stato alterato in transito (integrità). Verificare la firma su ogni richiesta in ingresso non è opzionale in produzione — senza di essa, chiunque potrebbe inviare payload falsi al tuo endpoint.

Per il setup dell’endpoint e la struttura degli eventi, vedi Ricevere eventi webhook.

Perché verificare la firma

I webhook espongono il tuo backend a richieste HTTP da internet. Anche con HTTPS, un attaccante potrebbe:

  • Inviare payload falsi — es. creare record CRM inesistenti o triggerare azioni indesiderate
  • Replay di eventi catturati — ripetere un evento legittimo per causare duplicati

La firma HMAC risolve entrambi i problemi: solo chi possiede il Webhook Secret (tu e Userbot) può generare una firma valida, e il timestamp limita la finestra di replay.

Algoritmo

Segui questi passi in ordine per ogni richiesta webhook:

  1. Estrai gli header x-userbot-signature e x-userbot-timestamp. Se mancano, rifiuta la richiesta con 401.
  2. Verifica il timestamp — deve essere entro ±5 minuti dal tempo corrente del tuo server. Eventi troppo vecchi o nel futuro lontano vanno scartati (anti-replay).
  3. Costruisci la stringa da firmare: {timestamp}.{raw_body} — usa il body HTTP grezzo così com’è arrivato, senza normalizzazioni JSON (spazi, ordine chiavi). Un body ri-serializzato produce una firma diversa.
  4. Calcola l’HMAC-SHA256 con il tuo Webhook Secret (fornito in dashboard alla creazione del webhook).
  5. Confronta il risultato esadecimale con x-userbot-signature usando un confronto timing-safe (es. crypto.timingSafeEqual in Node.js, hmac.compare_digest in Python) — evita confronti stringa diretti che possono leakare informazioni.

Pseudocodice

message = "{timestamp}.{raw_request_body}"
expected_signature = HMAC-SHA256(webhook_secret, message)
is_valid = timing_safe_compare(expected_signature, x-userbot-signature)

Se is_valid è false, rispondi 401 e non processare il payload.

Retry e deduplicazione

Anche con firma valida, lo stesso evento può arrivare più volte. Userbot ritenta la consegna se il tuo server non risponde con 200 entro 5 secondi — timeout, errori 5xx o elaborazioni troppo lente causano retry.

L’header x-userbot-attempt indica il numero del tentativo (1, 2, 3…). Implementa deduplicazione basata su:

  • eventId — presente in ogni payload e nell’header x-userbot-event-id
  • data.messageId — per l’evento message.added, utile come chiave aggiuntiva

Prima di elaborare, controlla se hai già processato quell’eventId. Se sì, rispondi 200 comunque (Userbot smette di ritentare) ma non ripetere l’azione di business.

Per un esempio completo di server con verifica HMAC, vedi la sezione “Esempio server” in Ricevere eventi webhook.

Checklist

  • Webhook Secret in secret manager, non in codice
  • Verifica timestamp ±5 minuti
  • Body grezzo per il calcolo HMAC, non JSON ri-parsato
  • Confronto timing-safe della firma
  • Deduplicazione per eventId prima dell’elaborazione