# Webhook spiegati semplicemente: firma, ripetizione, sicurezza

> Che cos'è un webhook, in che cosa differisce dalla richiesta API e come gestire firma, ripetizione e duplicati. Con curl e Node.

Quelle: https://whovisit.app/it/blog/webhook-spiegati-semplici-firma-sicurezza
Veröffentlicht: 2026-11-07
Herausgeber: Whovisit (ARAVILO, Innsbruck)

Un webhook è una telefonata nella direzione opposta. Invece di chiedere a un servizio ogni pochi minuti se sia successo qualcosa, il Suo sistema fa sì che sia il servizio a richiamare un indirizzo presso di Lei non appena accade. Risparmia richieste e porta le novità più in fretta. In cambio deve predisporre e proteggere un destinatario. Questo articolo spiega entrambe le cose.

## Webhook o richiesta API

| | Richiesta API (polling) | Webhook |
|---|---|---|
| Chi inizia? | Il Suo sistema | Il mittente |
| Quando? | Secondo un piano, ad esempio ogni ora | Non appena si verifica un evento |
| Impegno | Richieste anche senza novità | Serve un destinatario raggiungibile |
| Adatto a | Rapporti, riconciliazione, ricarica | Notifica, inoltro |
| Rischio | Ritardo fino alla richiesta successiva | Il messaggio va perso se il destinatario non risponde |

Nella pratica molti combinano le due cose: il webhook segnala l'evento, l'API recupera all'occorrenza i dettagli o colma le lacune dopo un'interruzione.

## Come si svolge una consegna

1. Si verifica un evento, ad esempio "pagamento ricevuto".
2. Il mittente invia un POST con JSON al Suo indirizzo registrato (HTTPS).
3. Il Suo destinatario verifica la firma, memorizza il messaggio e risponde rapidamente con un codice dell'intervallo 2xx.
4. Il lavoro vero e proprio lo svolge poi il Suo sistema.

Il passaggio 3 è importante. Stripe raccomanda nella [documentazione sui webhook](https://docs.stripe.com/webhooks) di restituire subito un codice 2xx, prima che giri una logica onerosa che potrebbe provocare un timeout. Chi prima registra la fattura e poi risponde rischia ripetizioni inutili.

## Firma: come verificare la provenienza

Il Suo indirizzo è raggiungibile pubblicamente. Chiunque potrebbe quindi inviargli messaggi inventati. Per questo i mittenti seri firmano ogni messaggio con un segreto condiviso. È consueto un HMAC con SHA-256 sul contenuto, spesso insieme a un timestamp. [GitHub descrive il procedimento](https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries) così: HMAC-SHA256 sul contenuto, rappresentato in esadecimale, con l'intestazione `X-Hub-Signature-256`. Il confronto deve avvenire con una funzione a tempo costante, in modo che gli aggressori non possano dedurre nulla dai tempi di risposta.

Punti importanti per il Suo destinatario:

- **Usare il contenuto grezzo.** Calcoli la firma sui byte ricevuti, non sul JSON serializzato di nuovo. Già un diverso ritorno a capo cambia la firma.
- **Verificare il timestamp.** Stripe usa un timestamp nella firma e una tolleranza predefinita di cinque minuti per impedire attacchi di replay. Una tolleranza di 0 disattiva la verifica.
- **Tenere segreto il segreto.** Non nel codice, non nel repository, ma in una variabile d'ambiente o in un caveau.

Linee guida open source per mittenti e destinatari le raccoglie l'iniziativa [Standard Webhooks](https://www.standardwebhooks.com/). Come ogni fornitore costruisca concretamente la propria firma è indicato nella sua documentazione.

## Ripetizioni e doppia consegna

Se il Suo destinatario non risponde o risponde con un codice di errore, il mittente riprova. Stripe, ad esempio, ripete secondo la propria documentazione con intervalli crescenti fino a tre giorni. Altri fornitori hanno altre regole, alcuni disattivano il webhook dopo troppi insuccessi. Ne consegue:

- **Metta in conto i duplicati.** Lo stesso evento può arrivare più volte, anche se il Suo destinatario lavora correttamente. Stripe lo segnala espressamente.
- **Renda idempotente l'elaborazione.** Cioè: chi elabora due volte lo stesso messaggio non produce un secondo risultato. Memorizzi l'identificativo dell'evento e salti ciò che già conosce.
- **Non si affidi all'ordine.** Gli eventi possono arrivare scambiati. Nel dubbio verifichi lo stato attuale tramite API.

## Sicurezza su entrambi i lati

**Per i destinatari:** solo HTTPS, verificare firma ed età, limitare la dimensione del messaggio, non eseguire comandi dal contenuto. Tratti il contenuto come qualsiasi input dall'esterno.

**Per i mittenti che richiamano indirizzi dei clienti:** chi offre webhook richiama indirizzi che altri hanno inserito. È una via classica per il Server-Side Request Forgery. L'aggressore inserisce un indirizzo interno. Il server lo richiama dall'interno della rete protetta. La [descrizione OWASP](https://community.owasp.org/attacks/Server_Side_Request_Forgery) indica come bersagli ad esempio servizi interni e indirizzi di metadati dei fornitori cloud. Misure di protezione sensate:

- ammettere solo `https://`,
- risolvere l'indirizzo all'inserimento e prima di ogni richiamo e rifiutare intervalli privati, locali e riservati,
- non seguire alla cieca i reindirizzamenti,
- impostare brevi limiti di tempo.

## Esempio: inviare un messaggio di prova con curl

Con curl e openssl può testare il Suo destinatario senza il vero mittente. Lo script invia un messaggio firmato, come lo invierebbe un mittente con timestamp:

```bash
GEHEIMNIS="test-geheimnis"
ZEIT=$(date +%s)
INHALT='{"id":"evt_1","typ":"besuch.begonnen","firma":"beispiel-firma.example"}'
SIGNATUR="sha256=$(printf '%s.%s' "$ZEIT" "$INHALT" | openssl dgst -sha256 -hmac "$GEHEIMNIS" | sed 's/^.* //')"

curl -X POST http://localhost:3000/webhook \
  -H "Content-Type: application/json" \
  -H "X-Zeit: $ZEIT" \
  -H "X-Signatur: $SIGNATUR" \
  -d "$INHALT"
```

## Esempio: un piccolo destinatario in Node.js

```js
const http = require('http')
const crypto = require('crypto')
const GEHEIMNIS = process.env.WEBHOOK_GEHEIMNIS || 'test-geheimnis'
const gesehen = new Set() // nella realtà: database

http.createServer((req, res) => {
  if (req.method !== 'POST' || req.url !== '/webhook') { res.writeHead(404); return res.end() }
  const teile = []
  req.on('data', t => teile.push(t))
  req.on('end', () => {
    const roh = Buffer.concat(teile).toString('utf8')
    const zeit = req.headers['x-zeit'] || ''
    const erwartet = 'sha256=' + crypto.createHmac('sha256', GEHEIMNIS).update(zeit + '.' + roh).digest('hex')
    const erhalten = String(req.headers['x-signatur'] || '')
    const a = Buffer.from(erwartet), b = Buffer.from(erhalten)
    const echt = a.length === b.length && crypto.timingSafeEqual(a, b)
    const frisch = Math.abs(Date.now() / 1000 - Number(zeit)) < 300
    if (!echt || !frisch) { res.writeHead(401); return res.end() }
    const ereignis = JSON.parse(roh)
    if (!gesehen.has(ereignis.id)) { gesehen.add(ereignis.id); console.log('neu:', ereignis.typ) }
    res.writeHead(200); res.end('ok')
  })
}).listen(3000)
```

Il destinatario verifica firma ed età, salta gli identificativi noti e risponde subito. Per l'esercizio servono inoltre HTTPS, un limite di dimensione e una coda per l'elaborazione successiva.

## Dove sono diffusi i webhook

Servizi di pagamento, piattaforme di codice e strumenti per moduli segnalano gli eventi tramite webhook. Lo può fare anche il riconoscimento dei visitatori: se il sistema segnala un'azienda che visita la Sua pagina, questa finisce direttamente in uno strumento di Sua scelta. Come questo porti a un sistema di vendita lo mostra [Portare le visite al sito web nel CRM](https://whovisit.app/blog/website-besuche-ins-crm). L'alternativa tramite richiesta la descrive [Quali aziende visitano il mio sito web?](https://whovisit.app/blog/welche-firmen-besuchen-meine-website). Quali dati confluiscano in questo caso lo spiega [Come funziona il riconoscimento delle aziende?](https://whovisit.app/blog/firmenerkennung-website-technik).

## Domande frequenti

**Qual è la differenza tra webhook e API?** Con l'API il Suo sistema chiede, con il webhook il mittente si fa vivo da sé. Le due cose si possono combinare.

**Che cosa succede se il mio destinatario si interrompe?** La maggior parte dei mittenti ripete la consegna per un certo periodo. Quanto a lungo e quanto spesso lo dice la documentazione del fornitore. Per le lacune dovrebbe prevedere una riconciliazione tramite API.

**Basta verificare l'indirizzo del mittente?** No. Gli indirizzi dei mittenti si possono falsificare e cambiano. Affidabile è solo la firma con un segreto che conoscono soltanto Lei e il mittente.
