Webhook-handtekeningen controleren: parse de JSON pas na verificatie

|Auteur: Redactie van QUASA|6 min. leestijd| 1
Webhook-handtekeningen controleren: parse de JSON pas na verificatie

Controleer een webhook met de ongewijzigde request body, het geheim van de verwachte verzender en diens handtekeningformaat. Parse de JSON en verwerk het event pas nadat die controle is geslaagd. Een leesbaar JSON-object bewijst op zichzelf niet wie het verzoek heeft verstuurd of dat de inhoud onderweg gelijk is gebleven.

De veilige volgorde is: ontvang de oorspronkelijke body en headers, verifieer de handtekening, parse daarna de inhoud en beslis vervolgens wat het event mag doen. Ontbreekt de handtekening of klopt ze niet, stop dan vóór een databasewijziging, wachtrijtaak of andere actie.

Houd de oorspronkelijke body beschikbaar

Laat de webhookroute de body ontvangen als ruwe bytes of als de exacte tekenreeks die de verificatiefunctie verwacht. De Stripe-instructies voor handtekeningfouten vereisen de ongewijzigde UTF-8-body: een parser die sleutels herschikt, witruimte verwijdert of de codering verandert, kan verificatie laten mislukken. Bij Stripe horen daar de waarde van Stripe-Signature en het geheim van het ontvangende endpoint bij; een lokaal via de Stripe CLI doorgestuurd endpoint heeft een ander geheim dan een in Stripe beheerd endpoint.

De wijziging kan al plaatsvinden voordat je eigen webhookfunctie draait. Controleer daarom waar algemene JSON-middleware, een proxy of een framework de body leest of omzet. Zorg dat de verificatiefunctie de oorspronkelijke inhoud krijgt en bewaar diezelfde inhoud voor het parsen na verificatie. Een opnieuw opgebouwd JSON-object kan inhoudelijk gelijk lijken, terwijl de bytes waarover de verzender de handtekening berekende anders zijn.

Bij een route waarop de body slechts eenmaal kan worden gelezen, leg je haar vast bij ontvangst en geef je die vastgelegde waarde aan de verificatiefunctie. Houd daarbij onderscheid tussen de ruwe invoer en het later geparste object: het object is geschikt voor eventvelden, maar kan de oorspronkelijke invoer niet betrouwbaar reconstrueren.

Volg één beslisvolgorde per verzoek

De verwerkingsvolgorde kan voor verschillende platforms gelijk zijn. Welke header, welk algoritme en welke invoer worden ondertekend, komt uit de specificatie van de betreffende verzender. Behandel een handtekening van een ander platform daarom niet alsof alleen de naam van de header verandert.

  1. Lees de body en de relevante headers zonder de body te muteren. Stel een passende limiet aan de omvang van het verzoek voordat je het volledig in het geheugen opneemt.
  2. Haal het geheim op dat bij dit endpoint en deze verzender hoort. Als het ontbreekt, accepteer het verzoek niet en behandel de ontbrekende configuratie als een serverprobleem. Sla geheimen buiten broncode en repository op.
  3. Controleer of de verwachte handtekeningheader aanwezig is en het voorgeschreven formaat heeft. Bereken de verwachte waarde over precies de invoer die de verzender voorschrijft. Gebruik bij een eigen implementatie voor geldige handtekeningwaarden een vergelijking in constante tijd.
  4. Wijs een ontbrekende of afwijkende handtekening af voordat je de body parseert of werk in een wachtrij plaatst. Geef een foutstatus terug zonder het geheim, de berekende handtekening of de volledige payload prijs te geven.
  5. Parse na een geslaagde verificatie de JSON en controleer het eventtype en de velden die jouw toepassing nodig heeft. Voer pas daarna de bijbehorende actie uit.

Zo blijven twee soorten fouten van elkaar te onderscheiden. Een verkeerde handtekening strandt bij de controle van afzender en integriteit; een correct ondertekende maar ongeldige JSON-body strandt pas bij het parsen. Dat onderscheid maakt een foutmelding bruikbaar zonder een onbevestigd verzoek al te verwerken.

Gebruik de verificatieregel van Stripe of GitHub

Voor Stripe geef je de oorspronkelijke body, Stripe-Signature en het juiste endpointgeheim aan de passende verificatiefunctie van de Stripe SDK. Die functie kan de controle combineren met het opbouwen van een event; laat dan geen eigen JSON-parser vóór de SDK-aanroep draaien. Controleer bij een afwijzing eerst of de route het bedoelde endpointgeheim gebruikt en daarna of middleware de body heeft gewijzigd.

De GitHub-handleiding voor webhookleveringen beschrijft een andere regel: X-Hub-Signature-256 bevat een met het webhookgeheim berekende HMAC-SHA256 over de payload, voorafgegaan door sha256=. GitHub adviseert verificatie vóór verdere verwerking, een geheim met hoge entropie dat niet in code of een repository staat, en een vergelijking in constante tijd in plaats van een gewone gelijkheidsoperator.

Gebruik bij een eigen HMAC-implementatie de bibliotheekfunctie voor veilige vergelijking en controleer het headerformaat voordat je waarden vergelijkt. Een verificatiefunctie uit de SDK of een daarvoor bestemde bibliotheek neemt vaak platformspecifieke details over. De algemene volgorde blijft bruikbaar, maar een Stripe-handtekening kun je niet met de GitHub-formule controleren.

Maak een afwijzing zichtbaar zonder gevoelige inhoud te loggen

Registreer bij een mislukte controle de webhookroute, een interne correlatie-id en een beperkte foutcategorie, zoals ontbrekende header, ongeldig formaat of geen overeenkomst. Daarmee kun je een configuratiefout onderscheiden van een gewijzigde body zonder geheimen of volledige payloads in logbestanden te bewaren. Een geslaagde parse van dezelfde body is geen reden om een mislukte handtekeningcontrole te negeren.

Onderzoek bij onverwachte afwijzingen de keten van ontvangst tot verificatiefunctie. Kijk of de verwachte header aanwezig blijft, of het juiste geheim is geladen en of de ingevoerde body nog overeenkomt met wat de server ontving. Een proxy die headers of inhoud aanpast, kan dezelfde klacht veroorzaken als middleware die JSON al heeft omgezet. Corrigeer de laag die de invoer verandert; herserialiseer het geparste object niet als vervanging van de originele body.

Test de route, inclusief middleware en herlevering

Test het volledige endpoint met een testgeheim en een ondertekende payload in het formaat van de gekozen verzender. Een losse test van de cryptografische functie ontdekt niet of middleware de body eerder heeft gewijzigd. Maak voor negatieve gevallen telkens een afzonderlijk verzoek, zodat duidelijk blijft welke grens de afwijzing veroorzaakt.

  • Een correct ondertekend verzoek bereikt de eventverwerking.
  • Dezelfde body zonder handtekening, met een verkeerd formaat of met een gewijzigde handtekening wordt afgewezen zonder neveneffect.
  • Een ondertekende body waarvan daarna één byte, een spatie of de sleutelvolgorde verandert, wordt afgewezen.
  • Een zelf samengestelde, correct ondertekende maar ongeldige JSON-body passeert de handtekeningcontrole en faalt vervolgens bij het parsen.
  • Een correct ondertekend event van een niet ondersteund type veroorzaakt geen bedrijfsactie.

Een geldige handtekening sluit herhaling van een eerder geldig verzoek niet uit. De GitHub-richtlijnen voor webhooks noemen X-GitHub-Delivery voor het herkennen van herhaalde leveringen; bij een handmatig aangevraagde herlevering blijft die waarde gelijk aan die van de oorspronkelijke levering. Koppel zo’n kenmerk aan de verwerkingsstatus: een al geslaagd event hoeft geen tweede actie te starten, terwijl een eerder mislukt event nog herstelbaar moet blijven.

Lees ook:

Delen:

Abonneer je op onze nieuwsbrief

Ontvang het laatste nieuws over Web3, AI en crypto rechtstreeks in je inbox.

0