---
title: "Webhook che arrivano, e cosa fare quando arrivano due volte"
summary: "Dodici eventi, una firma su timestamp e corpo, otto tentativi in circa 21 ore e un id per evento, così scartare i duplicati costa poco."
author: "Samuel Krauss"
author_title: "Founder"
publisher: "Elchi Studios"
published: 2026-10-03
updated: 2026-10-09
url: https://elchi.dev/it/journal/webhook-che-arrivano
language: it
translation_of: https://elchi.dev/en/journal/webhooks-that-arrive
tags: ["eauth","webhooks","integration"]
words: 1123
---

# Webhook che arrivano, e cosa fare quando arrivano due volte

*Di Samuel Krauss, Founder. Pubblicato il 3 ottobre 2026.*

> Dodici eventi, una firma su timestamp e corpo, otto tentativi in circa 21 ore e un id per evento, così scartare i duplicati costa poco.

Un provider di accesso che si limita a rispondere alle domande è un provider a metà. Il Suo sistema deve sapere quando una persona si registra, quando accede, quando revoca l'accesso della Sua applicazione o quando l'account viene cancellato, senza doverlo chiedere di continuo. EAuth Glielo comunica tramite webhook, e questo articolo parla delle parti che decidono se un'integrazione via webhook regge in produzione: cosa viene inviato, come sapere che viene da noi, cosa succede quando il Suo server è giù e cosa fare con una consegna già vista.

## Cosa viene inviato

Dodici eventi. Sette riguardano le persone e le loro sessioni: `user.created` quando qualcuno si registra o il single sign-on crea un account; `user.signed_in` a ogni codice di autorizzazione che Lei scambia, non ai refresh; `consent.granted` e `consent.revoked`; `session.revoked` con un motivo, ogni volta che i Suoi refresh token per qualcuno smettono di funzionare senza che Lei lo abbia chiesto, il che comprende il logout ovunque, un reset della password, un token usato due volte e una persona che lascia un'organizzazione; `user.password_changed`; e `user.deleted`. Cinque riguardano le organizzazioni: una creata, una cancellata, e un membro aggiunto, aggiornato o rimosso. Un endpoint non iscritto a nulla li riceve tutti.

Ogni corpo è un piccolo oggetto JSON: l'id e il tipo dell'evento, quando è avvenuto, il Suo client id e un oggetto `data` con degli id e poco altro. Se Le servono il nome o l'indirizzo attuali della persona, li chiede all'API con l'id. Un webhook che portasse il profilo sarebbe una copia che invecchia nel momento stesso in cui viene scritta.

Dal 3 ottobre una regola si vede nell'ordine degli eventi: nessuna applicazione riceve un account il cui indirizzo e-mail non sia confermato. `user.created` arriva ancora nel momento in cui qualcuno si registra, con `email_verified` false, ma la Sua applicazione non riceve alcun token per quella persona finché non ha aperto il link. Quindi `user.signed_in` arriva dopo la conferma, e chi non conferma mai Le lascia un `user.created` e nient'altro. Un account creato dal single sign-on arriva con `email_verified` true.

## Come sapere che viene da noi

Ogni consegna porta `Elchi-Signature: t=<timestamp>,v1=<hmac>`, dove l'HMAC-SHA256 è calcolato con il secret del Suo endpoint sul timestamp, un punto e il corpo grezzo. Lo schema è quello di Stripe con l'header rinominato, quindi a un verificatore esistente basta cambiare una riga. Lo verifichi sui byte grezzi ricevuti, prima di fare il parsing di qualsiasi cosa, con un confronto a tempo costante, e rifiuti un timestamp che si scosta di più di cinque minuti dal Suo orologio. È il timestamp dentro la stringa firmata a rendere inutile, in seguito, una consegna intercettata: il corpo di un evento `user.deleted` non cambia mai, quindi senza il timestamp un replay sarebbe indistinguibile dall'originale.

Il secret comincia con `whsec_`, così uno trapelato si riconosce in un log o nella scansione di un repository, e viene mostrato una volta sola, quando l'endpoint viene creato. Da parte nostra non può essere un digest, perché deve firmare ogni consegna, quindi è salvato cifrato con AES-256-GCM sotto una chiave che non tocca mai il database. L'esportazione della Sua applicazione lo esclude. Non c'è un pulsante di rotazione: per cambiare il secret, aggiunga un secondo endpoint con lo stesso URL, accetti entrambi i secret finché il nuovo non consegna, poi cancelli il vecchio. Durante questa sovrapposizione ogni evento arriva due volte con lo stesso id, cosa che la sezione dopo la prossima rende innocua.

## Cosa succede quando il Suo server è giù

Una consegna che non riceve una risposta 2xx entro dieci secondi è fallita. Ogni evento ha otto tentativi: il primo subito, poi dopo 30 secondi, 2, 10 e 30 minuti, e 2, 6 e 12 ore, ogni attesa contata dal tentativo precedente. L'ultimo tentativo arriva circa 21 ore dopo il primo, e una consegna che fallisce anche allora viene segnata come abbandonata.

Anche l'endpoint nel suo insieme ha un limite. Dopo 25 tentativi falliti di fila, contati su tutti i suoi eventi, viene spento, e la console lo segna come disattivato. Non parte nessuna e-mail. Mentre è spento, per lui non si accoda nulla: gli eventi che avvengono in quel periodo non vengono mai consegnati. Le consegne già in attesa riprendono quando Lei riattiva l'endpoint nella console, e una consegna abbandonata può essere reinviata a mano.

Messo insieme, ecco il compromesso. Un'applicazione tranquilla il cui ricevitore resta giù per dieci minuti non perde nulla: una manciata di eventi, qualche nuovo tentativo ciascuno. Una molto attiva arriva a 25 tentativi falliti nel giro di minuti, e da lì finché qualcuno non riattiva l'endpoint i suoi eventi sono persi. Dopo un'interruzione del Suo ricevitore, guardi la console, non solo i Suoi log.

Dieci secondi non sono molti, ed è voluto. Risponda 200 appena ha salvato il corpo e faccia il lavoro dopo. Un handler che chiama altri tre servizi prima di rispondere viene ritentato come uno fallito, e così gira quattro volte.

## Cosa fare con una consegna già vista

Ogni tentativo di un evento porta lo stesso `Elchi-Event-Id`, che è anche l'`id` nel corpo. Lo salvi insieme al lavoro fatto e, quando arriva un id che ha già, risponda 200 e scarti il corpo senza fare il parsing. Questa sola regola trasforma la consegna at-least-once, che è ciò che ogni sistema di webhook può onestamente offrire, in un'elaborazione exactly-once dalla Sua parte.

Rende anche sicuro premere il pulsante di reinvio. La console elenca per ogni endpoint le otto consegne più recenti con stato, codice di risposta, tentativi e orario, e ognuna di esse che non è stata consegnata può essere inviata di nuovo. Le consegne vengono conservate per 30 giorni e poi cancellate insieme ai payload, perché un payload nomina una persona.

## Regole per l'URL

Solo `https`, con un host e senza credenziali. `localhost` e gli indirizzi privati o riservati scritti letteralmente vengono rifiutati quando l'endpoint viene registrato. Un nome host viene controllato quando viene usato: ogni indirizzo a cui si risolve viene ricontrollato a ogni connessione, quindi un nome che in seguito punta dentro una rete viene comunque rifiutato. È il controllo che impedisce di usare un sistema di webhook per raggiungere un server che non dovrebbe mai vedere. I redirect non vengono seguiti, perché seguirne uno potrebbe trasformare un POST firmato in una richiesta verso un posto che Lei non ha mai registrato.

## Cosa non c'è

Non c'è batching e non c'è garanzia d'ordine tra gli eventi: due eventi per la stessa persona possono arrivare in disordine quando uno viene ritentato, quindi gestisca ciascuno in base ai propri fatti, `session.revoked` compreso. Non c'è un evento per un'importazione, perché il Suo sistema conosce già quelle persone. Non c'è una coda per il periodo in cui un endpoint è spento, né un'e-mail quando succede. E la console mostra le ultime otto consegne per endpoint, non un log consultabile dei 30 giorni.

## Fonti

1. [Webhooks, EAuth documentation](https://docs.elchi.dev/webhooks), Elchi Studios, consultato il 2026-10-03
2. [RFC 2104: HMAC: Keyed-Hashing for Message Authentication](https://www.rfc-editor.org/rfc/rfc2104.html), IETF, consultato il 2026-10-03
3. [Resolve webhook signature verification errors](https://docs.stripe.com/webhooks/signature), Stripe, consultato il 2026-10-03
4. [Server-Side Request Forgery Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html), OWASP, consultato il 2026-10-03
