Webhooks erklärt: Signierte Payloads und Retry-Strategien
Sie haben gerade einen Drittanbieter-Dienst integriert, der Webhooks sendet, und im Test funktioniert alles einwandfrei. In der Produktion stellen Sie jedoch gelegentlich verpasste Events, doppelte Zustellungen oder – schlimmer noch – einen Angreifer fest, der gefälschte Payloads an Ihren Endpoint sendet. Webhooks sind konzeptionell einfach, in der Praxis jedoch knifflig. Dieser Artikel erklärt, wie Sie Webhooks mit signierten Payloads absichern und robuste Retry-Strategien implementieren, damit Sie Ihren eventgetriebenen Integrationen vertrauen können.
Was sind Webhooks und warum sie wichtig sind
Webhooks sind benutzerdefinierte HTTP-Callbacks, die durch bestimmte Events ausgelöst werden. Wenn ein Event eintritt – etwa eine erfolgreiche Zahlung oder eine neue Nutzerregistrierung – sendet der Quell-Dienst eine HTTP-POST-Anfrage an eine von Ihnen angegebene URL. Dieses push-basierte Modell ist effizienter als Polling, da es Latenz und Serverlast reduziert. Es bringt jedoch Herausforderungen mit sich: die Echtheit zu verifizieren und Zustellungsfehler zu behandeln.
Webhooks mit signierten Payloads absichern
Ohne Verifikation kann jeder Anfragen an Ihren Webhook-Endpoint senden. Signierte Payloads lösen dieses Problem, indem sie eine kryptografische Signatur enthalten, die belegt, dass die Anfrage vom vertrauenswürdigen Absender stammt.
So funktionieren HMAC-Signaturen
Die meisten Anbieter verwenden HMAC (Hash-based Message Authentication Code) mit einem gemeinsamen Secret. Der Absender berechnet einen Hash des Payloads mit dem Secret und fügt ihn in einen Header ein (z. B. X-Signature). Ihr Server berechnet den Hash neu und vergleicht ihn. Stimmen sie überein, ist die Anfrage authentisch.
// Beispiel: Verifizieren einer Webhook-Signatur in Node.js
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
hmac.update(payload);
const digest = hmac.digest('hex');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest));
}
Wichtig: Verwenden Sie stets einen zeitkonstanten Vergleich, um Timing-Angriffe zu verhindern. Verifizieren Sie die Signatur außerdem gegen den rohen Request-Body und nicht gegen ein geparstes JSON-Objekt, da das Parsen den Payload verändern kann.
Best Practices für die Signaturverifikation
- HTTPS verwenden: Stellen Sie Webhooks immer über TLS bereit, um Abhören zu verhindern.
- Secrets rotieren: Rotieren Sie Ihr Signing-Secret regelmäßig und unterstützen Sie während der Rotation mehrere aktive Secrets.
- Timestamp validieren: Fügen Sie einen Zeitstempel in die Signatur ein, um Replay-Angriffe zu verhindern. Weisen Sie Anfragen zurück, die älter als einige Minuten sind.
- Fehler protokollieren: Überwachen Sie fehlgeschlagene Signaturverifikationen, um Angriffe oder Fehlkonfigurationen zu erkennen.
Zuverlässige Retries implementieren
Selbst mit signierten Payloads können Netzwerkprobleme oder temporäre Ausfälle dazu führen, dass die Webhook-Zustellung fehlschlägt. Eine robuste Retry-Strategie stellt sicher, dass Events letztendlich zugestellt werden, ohne Ihr System zu überlasten.
Exponentielles Backoff mit Jitter
Sofortiges Wiederholen kann die Überlastung verschlimmern. Verwenden Sie stattdessen exponentielles Backoff: Warten Sie zwischen jedem Retry länger. Fügen Sie Jitter (zufällige Variation) hinzu, um Thundering-Herd-Probleme zu vermeiden, wenn viele Webhooks gleichzeitig fehlschlagen.
// Beispiel: Retry-Zeitplan mit exponentiellem Backoff und Jitter
function getRetryDelay(attempt) {
const base = 1000; // 1 Sekunde
const max = 30000; // 30 Sekunden
const delay = Math.min(base * Math.pow(2, attempt), max);
return delay + Math.random() * 1000; // bis zu 1s Jitter hinzufügen
}
Idempotenz: Duplikate behandeln
Retries können doppelte Zustellungen verursachen. Ihr Webhook-Handler muss idempotent sein – dasselbe Event mehrfach zu verarbeiten, sollte dieselbe Wirkung haben wie eine einmalige Verarbeitung. Verwenden Sie die Event-ID aus dem Payload, um verarbeitete Events nachzuverfolgen.
- Speichern Sie verarbeitete Event-IDs in einer Datenbank mit einer TTL.
- Prüfen Sie vor der Verarbeitung, ob die Event-ID bereits existiert; falls ja, geben Sie sofort eine Erfolgsantwort zurück.
- Gestalten Sie Operationen idempotent (z. B. Upserts statt Inserts verwenden).
Schnell antworten und bestätigen
Ihr Webhook-Endpoint sollte so schnell wie möglich mit einem 2xx-Statuscode antworten – idealerweise innerhalb weniger Sekunden. Wenn die Verarbeitung länger dauert, reihen Sie das Event zur asynchronen Verarbeitung in eine Queue ein und geben Sie 202 Accepted zurück. Dies verhindert Timeouts und unnötige Retries.
Vergleich: Webhooks vs. Polling
| Aspekt | Webhooks | Polling |
|---|---|---|
| Latenz | Nahezu Echtzeit | Abhängig vom Intervall |
| Serverlast | Gering (nur Push) | Hoch (konstante Anfragen) |
| Komplexität | Höher (Retries, Sicherheit nötig) | Geringer |
| Zuverlässigkeit | Erfordert Retry-Logik | Von Natur aus zuverlässig |
Schritt für Schritt: Einen sicheren Webhook-Receiver bauen
- Richten Sie einen HTTPS-Endpoint mit einem gültigen Zertifikat ein.
- Extrahieren Sie den Signatur-Header (z. B.
X-Signature) und den Zeitstempel. - Verifizieren Sie die Signatur mit dem gemeinsamen Secret und dem rohen Body.
- Prüfen Sie den Zeitstempel, um alte Anfragen zurückzuweisen (z. B. älter als 5 Minuten).
- Parsen Sie den Payload und prüfen Sie auf doppelte Event-IDs.
- Verarbeiten Sie das Event bei Bedarf asynchron und antworten Sie mit 200 OK.
- Protokollieren Sie das Event für Auditing und Debugging.
FAQ
Was ist ein signierter Webhook-Payload?
Ein signierter Payload enthält eine kryptografische Signatur (üblicherweise HMAC), die es dem Empfänger ermöglicht zu verifizieren, dass die Anfrage von einer vertrauenswürdigen Quelle stammt und nicht manipuliert wurde.
Wie oft sollte ich einen fehlgeschlagenen Webhook wiederholen?
Die meisten Systeme wiederholen 3–5 Mal mit exponentiellem Backoff. Danach wird das Event in der Regel als fehlgeschlagen markiert und erfordert möglicherweise manuelles Eingreifen oder die Behandlung über eine Dead-Letter-Queue.
Kann ich Webhooks ohne HTTPS verwenden?
Davon wird dringend abgeraten. Ohne HTTPS können Payloads und Signaturen abgefangen oder verändert werden. Verwenden Sie für Webhook-Endpoints immer TLS.
Beim Debuggen von Webhook-Payloads oder -Logs ist die korrekte Formatierung von JSON entscheidend. Nutzen Sie unseren JSON Formatter, um JSON-Payloads schnell übersichtlich darzustellen und zu validieren.