Webhooks erklärt: Signierte Payloads und Retries

Backend2026-10-29TryQuickToolBox

Sie haben gerade einen Zahlungsanbieter eines Drittanbieters integriert. In der Dokumentation steht: „Wir senden einen Webhook, wenn eine Zahlung erfolgreich ist.“ Einfach, oder? Aber dann stellen Sie fest: Woher wissen Sie, dass die Anfrage wirklich von ihnen kommt? Was ist, wenn Ihr Server nicht erreichbar ist, wenn sie ihn senden? Was ist, wenn sie dasselbe Ereignis zweimal senden?

Webhooks sind leistungsstark, erfordern aber eine sorgfältige Handhabung. Dieser Leitfaden behandelt die Grundlagen: das Signieren von Payloads zur Überprüfung der Authentizität, die Implementierung von Wiederholungsversuchen zur Behandlung von Fehlern und die Gewährleistung von Idempotenz zur Vermeidung doppelter Verarbeitung.

Was sind Webhooks?

Ein Webhook ist ein HTTP-Callback: Anstatt dass Ihre App eine API auf Änderungen abfragt, sendet der Anbieter bei Auftreten eines Ereignisses eine HTTP-POST-Anfrage an eine von Ihnen angegebene URL. Dies macht Integrationen effizient und nahezu in Echtzeit.

Häufige Beispiele sind Zahlungsbenachrichtigungen (Stripe, PayPal), CI/CD-Trigger (GitHub, GitLab) und Messaging-Plattformen (Slack, Discord).

Warum Webhooks mit Signaturen absichern?

Ihr Webhook-Endpunkt ist öffentlich zugänglich. Jeder kann eine POST-Anfrage an ihn senden. Ohne Überprüfung könnte ein Angreifer Ereignisse fälschen – beispielsweise eine unbezahlte Bestellung als bezahlt markieren.

Das Signieren von Payloads mit einem gemeinsamen Geheimnis ermöglicht es Ihnen zu überprüfen, ob die Anfrage vom erwarteten Absender stammt und ob der Payload nicht manipuliert wurde.

Wie HMAC-Signaturen funktionieren

Der Anbieter und Sie teilen einen geheimen Schlüssel. Für jeden Webhook berechnet der Anbieter einen HMAC (Hash-based Message Authentication Code) des Payloads mit diesem Geheimnis und fügt die Signatur in einen Header ein (z. B. X-Signature). Sie berechnen den HMAC auf Ihrer Seite neu und vergleichen.

HMAC gewährleistet Integrität und Authentizität, da nur jemand mit dem Geheimnis eine gültige Signatur erzeugen kann.

Implementierung signierter Payloads

Lassen Sie uns eine typische Implementierung in Node.js (Express) und Python (Flask) durchgehen. Die Prinzipien gelten für jede Sprache.

Schritt 1: Geheimnis erhalten und speichern

Bei der Registrierung des Webhooks gibt Ihnen der Anbieter ein Geheimnis. Speichern Sie es sicher – in Umgebungsvariablen oder einem Secrets Manager – niemals im Code.

Schritt 2: Den Rohtext erfassen

Die Signaturüberprüfung erfordert die exakten Rohbytes des Bodys. Wenn Ihr Framework JSON analysiert, bevor Sie überprüfen, kann eine erneute Serialisierung die Bytes verändern und die Überprüfung fehlschlagen lassen.

Verwenden Sie in Express express.raw({ type: 'application/json' }) für die Webhook-Route. Greifen Sie in Flask auf request.get_data() vor der Analyse zu.

Schritt 3: Signaturen berechnen und vergleichen

Verwenden Sie eine Vergleichsfunktion mit konstanter Zeit, um Timing-Angriffe zu verhindern.

// Node.js (Express)
const crypto = require('crypto');

app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-signature'];
  const secret = process.env.WEBHOOK_SECRET;
  const expected = crypto.createHmac('sha256', secret).update(req.body).digest('hex');
  
  if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process event
  const event = JSON.parse(req.body);
  // ... handle event
  res.status(200).send('OK');
});

Verwenden Sie in Python hmac.compare_digest:

# Python (Flask)
import hmac, hashlib, os
from flask import request, abort

@app.route('/webhook', methods=['POST'])
def webhook():
    signature = request.headers.get('X-Signature')
    secret = os.environ['WEBHOOK_SECRET'].encode()
    expected = hmac.new(secret, request.get_data(), hashlib.sha256).hexdigest()
    if not hmac.compare_digest(signature, expected):
        abort(401)
    event = request.get_json()
    # ... handle event
    return 'OK', 200

Schritt 4: Zeitstempel behandeln (optional, aber empfohlen)

Einige Anbieter fügen einen Zeitstempel in die Signatur ein, um Replay-Angriffe zu verhindern. Beispielsweise signiert das Schema von Stripe timestamp.payload. Sie sollten Anfragen mit Zeitstempeln ablehnen, die zu weit in der Vergangenheit liegen (z. B. älter als 5 Minuten).

Implementierung von Wiederholungsversuchen

Netzwerke versagen. Ihr Server könnte ausgefallen sein oder die Anfrage könnte eine Zeitüberschreitung haben. Zuverlässige Webhook-Systeme wiederholen fehlgeschlagene Zustellungen.

Auf der Anbieterseite

Wenn Sie den Webhook-Sender erstellen, implementieren Sie Wiederholungsversuche mit exponentiellem Backoff. Ein übliches Muster: Wiederholung nach 1 Minute, dann 5 Minuten, dann 30 Minuten usw., bis zu einer maximalen Anzahl von Versuchen (z. B. 5). Fügen Sie eine eindeutige Ereignis-ID in den Payload ein, damit der Empfänger deduplizieren kann.

Auf der Empfängerseite

Als Empfänger sollten Sie:

Idempotenz: Umgang mit doppelten Ereignissen

Wiederholungsversuche können zu doppelten Ereignissen führen. Verwenden Sie die Ereignis-ID (von den meisten Anbietern bereitgestellt), um verarbeitete Ereignisse zu verfolgen. Prüfen Sie vor der Verarbeitung, ob die ID bereits gesehen wurde; wenn ja, überspringen Sie sie.

Speichern Sie verarbeitete IDs in einer Datenbank mit einer TTL oder verwenden Sie einen Idempotenzschlüssel in Ihrer Geschäftslogik.

Webhooks lokal testen

Während der Entwicklung ist Ihr lokaler Server nicht öffentlich zugänglich. Tools wie ngrok oder localtunnel erstellen eine öffentliche URL, die zu Ihrem Rechner tunnelt. Alternativ können Sie einen Webhook-Testdienst verwenden, der Anfragen erfasst und Ihnen das erneute Abspielen ermöglicht.

Häufige Fallstricke und Best Practices

Vergleich: Signierte vs. unsignierte Webhooks

AspektSigniertUnsigniert
SicherheitHoch: überprüft Herkunft und IntegritätNiedrig: jeder kann fälschen
ImplementierungsaufwandMittel: HMAC berechnen und vergleichenMinimal
Empfohlen fürAlle ProduktionssystemeNur interne, vertrauenswürdige Netzwerke

FAQ

Wie überprüfe ich eine Webhook-Signatur?

Berechnen Sie einen HMAC des Rohtexts der Anfrage mit dem gemeinsamen Geheimnis und vergleichen Sie ihn dann mit dem Signatur-Header mithilfe einer Funktion mit konstanter Zeit. Verwenden Sie immer den Rohtext, nicht analysiertes JSON.

Was sollte mein Webhook-Endpunkt zurückgeben?

Geben Sie schnell einen 2xx-Statuscode zurück, um den Empfang zu bestätigen. Wenn die Verarbeitung fehlschlägt, geben Sie einen 5xx zurück, um eine Wiederholung auszulösen, aber stellen Sie sicher, dass Ihr Endpunkt idempotent ist, um Duplikate zu verarbeiten.

Wie oft wird ein Webhook wiederholt?

Das hängt vom Anbieter ab. Die meisten wiederholen mehrmals mit exponentiellem Backoff über einen Zeitraum von Stunden oder Tagen. Überprüfen Sie die Dokumentation des Anbieters für Details.

Beim Debuggen von Webhook-Zustellungen ist die Inspektion von Serverprotokollen oft notwendig. Wenn Sie Nginx verwenden, kann der Nginx Log Analyzer Ihnen helfen, Zugriffsprotokolle zu analysieren und fehlgeschlagene Anfragen oder ungewöhnliche Muster zu erkennen.