Come funziona la verifica della firma di un webhook
La firma di un webhook è una breve prova che l’evento proviene dal fornitore del servizio di pagamento e non da una richiesta POST qualsiasi. Il fornitore firma il payload con un segreto condiviso o una chiave privata; poi la tua app verifica la firma prima di fidarsi dell’evento. Se la firma non è valida, la risposta più sicura è un errore 401 o 400 e nessun aggiornamento dell’ordine.
Sembra semplice. Di rado lo è.
In pratica, la verifica della firma ti protegge da fatture contraffatte, rimborsi falsi e payload manomessi che a prima vista sembrano legittimi. Un webhook che segnala «pagamento completato» non serve a molto se chiunque può falsificarlo. Per i team che seguono una guida ai gateway di pagamento in criptovalute per l’e-commerce, questa verifica è il passaggio tra l’accettazione del pagamento e l’evasione dell’ordine: basta un presupposto errato per bloccare l’intero flusso.
La maggior parte dei fornitori firma l’intero corpo grezzo della richiesta, un timestamp o entrambi. Alcuni usano HMAC-SHA256, altri un’intestazione versionata con più valori di firma. Basta una sola discrepanza. Il fornitore potrebbe aver ragione e la tua app potrebbe comunque rifiutare l’evento, anche se hai modificato un solo byte. Se ti stai chiedendo come verificare la firma di un webhook, parti dai byte effettivamente ricevuti, dal segreto corretto e dal formato dell’intestazione previsto dal fornitore.
Per prima cosa, verifica che il problema riguardi davvero la firma
I log dovrebbero permetterti di capirlo in meno di 5 minuti. Se non ci riesci, non sono abbastanza dettagliati.
Controlla il codice di risposta esatto e il messaggio di errore. Un 400 con «firma non valida» indica una cosa; un 500 o un timeout ne indica un’altra. Errori di consegna, route non corrette, problemi TLS e timeout del proxy possono sembrare problemi del webhook nella dashboard, ma non sono la stessa cosa. Se il fornitore indica «consegnato» e il tuo endpoint restituisce 200, è improbabile che la verifica della firma sia la causa del problema.
Controlla insieme tre elementi: il log di consegna del fornitore, il log dell’applicazione e, se ne hai uno, il log del proxy inverso. Una richiesta che non raggiunge mai il tuo codice non può fallire la verifica della firma. Una richiesta che arriva al tuo codice ma restituisce 401, invece, di solito può farlo. Un dettaglio importante: se l’evento compare nei log ma non c’è alcun errore di firma, il codice potrebbe rifiutare il payload in un secondo momento, dopo la verifica.
In breve: accertati del problema prima di modificare il codice. Questo è il primo passo per risolvere errori di firma webhook senza introdurre modifiche inutili o rischiose.
Controlla il segreto condiviso o la chiave di firma
È l’errore più comune e, proprio perché sembra banale, può essere insidioso. Il segreto del webhook nella tua applicazione deve corrispondere esattamente a quello attuale nella dashboard dei pagamenti, inclusi eventuali spazi nascosti copiati da un campo di testo. Se il fornitore ha cambiato il segreto martedì scorso, la vecchia chiave sarà ancora nelle variabili d’ambiente finché qualcuno non la aggiorna.
Confronta il segreto nella dashboard con quello nell’ambiente di distribuzione, non solo con quello sul tuo computer. Produzione, staging e sviluppo locale dovrebbero avere valori distinti. Un team che copia in produzione un segreto di test può perdere 2 ore a cercare la causa di un errore di firma dovuto a una stringa incollata per sbaglio. È un problema frequente durante il lancio e le migrazioni da un processore di pagamento a un altro. Per i team che seguono una guida ai gateway di pagamento in criptovalute per l’e-commerce, le discrepanze tra i segreti emergono spesso subito dopo il rilascio di una nuova procedura di checkout.
Conserva le vecchie chiavi solo se il fornitore supporta la rotazione con un periodo di sovrapposizione. Se entrambe le chiavi, vecchia e nuova, restano valide per un breve periodo, il verificatore dovrebbe provare prima quella attiva e poi quella precedente. Se il fornitore non supporta la sovrapposizione, rimuovi la vecchia chiave da tutti gli ambienti. Niente supposizioni.
Ricostruisci il corpo grezzo della richiesta esattamente com’è arrivato
È qui che molte implementazioni ben fatte falliscono. Le verifiche della firma dipendono di solito dai byte grezzi esatti inviati dal fornitore, non dall’oggetto JSON creato dal framework dopo l’analisi. Per questo la verifica webhook HMAC con corpo grezzo richiede di conservare e usare il corpo originale prima che il framework lo analizzi o lo trasformi. Se il codice converte i numeri, riordina i campi, elimina gli spazi o normalizza le interruzioni di riga, la firma calcolata può cambiare anche se il payload «sembra» identico.
Alcuni framework leggono il corpo una volta e poi eliminano il flusso originale. Altri analizzano automaticamente il JSON prima che venga eseguito il middleware. Di conseguenza, il verificatore riceve un oggetto ricostruito, non il corpo grezzo. Di solito la soluzione consiste nel salvare prima il payload senza modificarlo e poi passare quel buffer esatto alla funzione di verifica della firma. Una sola impostazione del framework può determinare se il corpo viene conservato o riscritto.
Per esempio, un payload con 14 campi potrebbe arrivare in un determinato ordine di byte, che il tuo codice non vedrà mai se l’analizzatore riordina le chiavi. Anche un’interruzione di riga finale può fare la differenza. Lo stesso vale per una singola conversione UTF-8. Sì, un solo carattere invisibile può compromettere l’intera verifica.
Se il tuo stack lo consente, registra la lunghezza del corpo e un hash della richiesta grezza prima di analizzarla. Non registrare i segreti. Registra invece il percorso esatto del codice che legge il flusso: sarà molto più facile capire perché testare un pagamento in criptovalute a volte funziona con Postman ma non con un webhook reale del fornitore.
Verifica il timestamp, la sincronizzazione dell’orologio e la protezione dai replay
Molti schemi di webhook includono un timestamp per impedire che eventi vecchi vengano riprodotti in un secondo momento. Il verificatore potrebbe rifiutare una richiesta se il timestamp supera una finestra di tolleranza, spesso di 5 minuti o di un altro intervallo stabilito dal fornitore. Questa protezione serve a contrastare gli attacchi di replay, ma significa anche che l’orologio del server deve essere corretto.
Controlla l’orologio di sistema su ogni server che gestisce i webhook. Se è avanti o indietro di 3 minuti, la firma potrebbe risultare non valida anche quando il payload è corretto. Se il server è in un container, verifica anche l’ora dell’host. NTP o un altro servizio di sincronizzazione dell’ora dovrebbe essere attivo sul computer che esegue la verifica. Un server con un errore di 10 minuti può trasformare un webhook valido in un falso errore.
Anche la protezione dai replay è importante. Se il codice memorizza le firme o gli ID degli eventi già ricevuti, assicurati che la durata della cache corrisponda alla finestra di replay prevista dal fornitore. Una voce obsoleta nella cache può causare il rifiuto di una ritrasmissione valida. Un nuovo tentativo del fornitore non equivale a un replay malevolo: il codice deve distinguere i due casi. È un dettaglio piccolo, ma con conseguenze importanti.
Assicurati che l’intestazione della firma venga analizzata correttamente
Le intestazioni delle firme non hanno tutte lo stesso formato. Alcuni fornitori inviano un’unica intestazione con un solo hash, mentre altri usano un elenco di coppie chiave-valore separate da virgole, un’etichetta di versione e un timestamp. Il parser deve corrispondere esattamente a quel formato. Se si aspetta v1= ma il fornitore invia t= insieme a più versioni, la verifica fallirà prima ancora che inizi la parte crittografica.
Fai attenzione agli errori di rimozione degli spazi. Gli spazi iniziali o finali contano, così come gli errori di codifica, quando un framework decodifica le intestazioni come Latin-1 invece che UTF-8. Un’interruzione di riga finita per errore in una variabile d’ambiente può far fallire il confronto. Non normalizzare l’intestazione, a meno che il fornitore non lo consenta. Non convertire in minuscolo un valore che deve poter contenere dati binari. Questi due errori causano più problemi del dovuto.
Anche la gestione di più schemi richiede attenzione. Alcuni fornitori pubblicano una firma attuale e una precedente durante il periodo di transizione. Il verificatore dovrebbe sapere quale versione sta usando e rifiutare in modo chiaro quelle sconosciute. Se l’intestazione include sia un timestamp sia una firma, verificali entrambi. Se il fornitore specifica un prefisso da includere nella firma, usalo esattamente come indicato. Per saperne di più sulla gestione sicura dei webhook, consulta le migliori pratiche di sicurezza per i pagamenti in criptovalute.
Prova un evento webhook di cui conosci la validità
Un evento sicuramente valido fa risparmiare tempo. Inviane di nuovo uno dalla dashboard del fornitore oppure usa un payload di esempio documentato e confronta la firma attesa con quella calcolata dal tuo codice. Se l’esempio viene verificato ma il traffico reale no, probabilmente il problema riguarda la configurazione, l’ambiente o la rotazione del segreto. Se non viene verificato nessuno dei due, il percorso del codice è errato.
Usa un solo ID evento e un solo timestamp. Poi confronta quattro elementi: corpo grezzo, valore dell’intestazione, segreto e orologio. Nella maggior parte dei casi basta questo per individuare il problema. Un payload di test copiato in un file locale potrebbe contenere una formattazione diversa da quella che il tuo endpoint riceve davvero, quindi, se disponibile, usa sempre lo strumento del fornitore per ritentare l’invio. Un nuovo invio è meglio di 20 tentativi alla cieca.
Se il fornitore offre uno strumento per calcolare la firma, usalo con lo stesso payload. Se il risultato differisce anche solo per un carattere, c’è un problema di analisi o di conservazione del corpo. Se invece il risultato corrisponde ma il fornitore continua a rifiutare la richiesta, il problema riguarda il segreto o l’analisi dell’intestazione. Questa distinzione ti indica dove cercare.
È anche il momento di separare chiaramente staging e produzione. Un evento di staging inviato usando un segreto di produzione fallirà sempre. Senza controllare l’etichetta dell’ambiente, l’errore sembrerà identico a una firma non valida.
Rendi l’endpoint webhook più sicuro e monitoralo
Una volta che la verifica della firma funziona, fai in modo che continui a funzionare. Registra l’ID dell’evento, il risultato della verifica, il nome del fornitore e quello dell’ambiente. Non registrare il segreto completo. Non registrare l’intero corpo grezzo se contiene dati sensibili dei clienti. Usa un messaggio di errore breve e chiaro per gli operatori e una risposta di rifiuto essenziale per il fornitore.
Cambia il segreto del webhook secondo una pianificazione e documenta il passaggio. Una rotazione in 2 fasi è più sicura: aggiungi la nuova chiave, verifica che entrambe funzionino se è supportata una sovrapposizione, poi rimuovi la vecchia. Usa endpoint separati per test e produzione, così un errore in staging non coinvolge gli ordini reali. Sembra ovvio, ma i team continuano a confonderli.
Invia un avviso se si verifica un’ondata di errori di firma, non per un singolo tentativo fallito. Un errore può dipendere da un nuovo tentativo non riuscito. Cinque errori in 1 minuto meritano attenzione. Includi nell’avviso la route, il fornitore e il codice di risposta, così chi è di turno può capire se il problema dipende da un segreto diverso, da un bug nel parser o dall’orologio. Se stai ancora configurando l’endpoint, l’articolo come configurare i pagamenti in criptovalute può aiutarti a mantenere semplice il percorso del webhook fin dall’inizio.
Un’ultima cosa: prepara una breve guida operativa con i passaggi esatti per correggere una firma webhook non valida per un pagamento in criptovalute, compresi dove si trova il segreto, come inviare di nuovo un evento e quale riga di log conferma la verifica. Una guida di 10 righe può farti risparmiare un’ora alle 2 di notte.




Comments