Den konkreten Absendervertrag lesen
Webhooks besitzen kein universelles Signaturformat. Der Anbieter legt fest, welche Bytes signiert werden, wo die Signatur steht, ob ein Zeitstempel enthalten ist und wie Zustellungen wiederholt werden. Ein Beispiel eines anderen Anbieters kann deshalb schon beim ersten Prüfschritt falsch sein.
Für Ihre Integration brauchen Sie einen kleinen Vertrag: erlaubte Ereignistypen, verwendetes Test-/Produktkonto, Signaturverfahren, Schlüsselwechsel, Antwortfrist, Wiederholungsregeln und Statusabgleich bei ausgefallener Zustellung. Abonnieren Sie nur Ereignisse, die Sie tatsächlich verarbeiten.
Auch bei einer E-Mail-Plattform ist ein Webhook zunächst ein API-Ereignis, etwa über einen Versandstatus. Seine Signatur ist keine DKIM-Signatur einer E-Mail und kein Beweis für Inboxplatzierung. Die E-Mail-Grundlagen behandeln die andere Ebene.
Die tatsächlich signierten Bytes prüfen
Beim von GitHub dokumentierten HMAC-Verfahren wird aus Webhook-Geheimnis und Requestbody ein Prüfwert berechnet. Der Empfänger vergleicht ihn mit dem Wert aus X-Hub-Signature-256. Eine geeignete Bibliothek übernimmt den Vergleich ohne datenabhängige frühe Abbrüche. GitHub: Validating webhook deliveries.
Verwenden Sie die vom Verfahren verlangten Originaldaten. Ein JSON-Parser mit anschließender Serialisierung kann Leerzeichen oder Reihenfolge ändern. Das Ergebnis kann fachlich dieselben Felder enthalten und trotzdem andere Bytes besitzen. Bei Stripe ist der unveränderte Requestbody ausdrücklich Voraussetzung der Signaturprüfung. Stripe: Webhooks.
Das Prinzip zeigt ein absichtlich kleines lokales Beispiel. Es demonstriert nur HMAC und Byteidentität, keinen produktionsfertigen Webhook-Endpunkt:
import hashlib
import hmac
secret = b"demo-only-not-a-production-secret"
raw_body = b'{"event_id":"demo-17","state":"ready"}'
signature = hmac.new(secret, raw_body, hashlib.sha256).hexdigest()
same_body = hmac.compare_digest(
signature,
hmac.new(secret, raw_body, hashlib.sha256).hexdigest(),
)
changed_body = hmac.compare_digest(
signature,
hmac.new(secret, raw_body + b" ", hashlib.sha256).hexdigest(),
)
assert same_body is True
assert changed_body is False
Der zusätzliche Abstand ändert den Prüfwert, obwohl er für die JSON-Bedeutung unerheblich sein kann. Ein echter Empfänger muss zusätzlich Headerformat, zulässigen Algorithmus, fehlende/mehrfache Angaben und maximale Bodygröße nach seinem Vertrag prüfen. Nutzen Sie bevorzugt die passende offizielle Bibliothek und klären Sie die Middleware-Reihenfolge, bevor ein allgemeiner JSON-Parser den Body verändert. Das fest eingetragene Demogeheimnis darf niemals in einen realen Dienst übernommen werden.
Frische und wiederholte Zustellung auseinanderhalten
Eine alte gültig signierte Nachricht kann erneut zugestellt werden. Manche Verfahren signieren deshalb einen Zeitstempel mit. Der Empfänger prüft ihn innerhalb einer zum Anbieter passenden Toleranz und benötigt eine verlässliche Uhr. Ein beliebiger unsignierter Date-Header liefert diese Eigenschaft nicht.
Stripe dokumentiert ein solches Zeitverfahren und erzeugt bei einem erneuten Zustellversuch neue Zeit-/Signaturwerte. Die dort beschriebene Toleranz ist anbieterspezifisch. Eine erfolgreiche Zeitprüfung verhindert weder zwei schnelle Wiederholungen innerhalb des Fensters noch die doppelte Verarbeitung eines vom Anbieter erneut zugestellten Ereignisses. Stripe: Replay attacks.
GitHub verwendet für die beschriebene HMAC-Prüfung den Body. Die Zustellkennung X-GitHub-Delivery kann bei erneuter Zustellung gleich bleiben, ist aber durch diese Body-Signatur nicht automatisch mitgeschützt. Behandeln Sie daher nicht jede frei übermittelte Kennung allein als kryptografischen Replaynachweis. Prüfen Sie die konkreten Eigenschaften des Verfahrens und sichern Sie die fachliche Wirkung zusätzlich ab. GitHub: Best practices.
Annahme dauerhaft sichern, danach zügig antworten
Lange Arbeit direkt im Empfangspfad kann die Antwortfrist überschreiten. Ein brauchbarer Entwurf nimmt nach erfolgreicher Signatur- und Grundprüfung einen Eintrag in eine dauerhafte Eingangstabelle oder Warteschlange auf. Erst wenn dieser Eintrag verlässlich gespeichert ist, bestätigt der Server die Annahme. Kann die Speicherung nicht erfolgen, darf eine positive Antwort keinen angenommenen Auftrag vortäuschen.
Schematische Erklärung · keine Messung
Erst dauerhaft annehmen, dann bestätigen
Beispiel mit nachgelagerter Verarbeitung: Die Antwort bestätigt die Annahme, nicht schon die fachliche Wirkung.
- Absender → Webhook-Empfang
Body begrenzt empfangen; Signatur und gegebenenfalls signierte Zeit prüfen.
- Empfang → geprüfte Zuordnung
Ereignisformat, Integration und Konto prüfen. Nur bei erfolgreicher Prüfung weiter.
- Empfang → dauerhafter Eingang
Ereignis oder bekannte Wiederholung verlässlich erfassen. Eine flüchtige Aufgabe im Arbeitsspeicher genügt nicht.
- Empfänger → Absender: Annahme bestätigen
Erst nach gesicherter Annahme nach Anbieter-Vertrag antworten. Bei Wiederholung muss die frühere Annahme sicher feststehen.
- Dauerhafter Eingang → Verarbeitung
Fachliche Zuordnung und erlaubten Zustandswechsel prüfen; Wirkung und Bearbeitungszustand konsistent festhalten.
Fehler und spätere Zustellungen
- Speicherung scheitert
- Keine positive Antwort, die eine Annahme vortäuscht.
- Prozessabbruch nach Bestätigung
- Offene Verarbeitung aus dem dauerhaften Eingang wieder aufnehmen. „Schon gesehen“ heißt nicht „erledigt“.
- Ereignis trifft verspätet ein
- Gegen den aktuellen Zustand prüfen; einen Abschluss nicht blind zurücksetzen.
Antwortfrist, Wiederholung und Reihenfolge richten sich nach dem Anbieter-Vertrag. Der Ablauf ist kein allgemeines „Exactly once“-Versprechen.
„Dauerhaft erfassen“ bedeutet mehr als eine flüchtige Aufgabe im Arbeitsspeicher. Bei einem Prozessabbruch direkt nach der HTTP-Antwort muss klar bleiben, was noch zu tun ist. Eine bekannte Wiederholung kann nach dem Vertrag erneut positiv bestätigt werden, wenn ihre frühere Annahme sicher feststeht.
Die Antwortfrist richtet sich nach dem Anbieter; GitHub nennt beispielsweise zehn Sekunden. Auch Wiederholungsregeln sind unterschiedlich: Planen Sie nicht allein mit der Annahme, der Absender werde jedes verlorene Ereignis unbegrenzt automatisch nachliefern. GitHub: Best practices.
Zustellung, Ereignis und Geschäftsaktion getrennt identifizieren
Für das Entdoppeln sind mehrere Kennungen nützlich, aber nicht austauschbar:
Bei schmaler Ansicht können Sie die Tabelle seitlich scrollen.
| Kennung | Zweck | Grenze |
|---|---|---|
| Zustellkennung | Einzelnen Transportversuch oder eine Anbieterzustellung zuordnen | Je Anbieter bei Wiederholung gleich oder neu; nicht immer vom Signaturverfahren erfasst |
| Ereigniskennung | Dasselbe Ereignis mehrfach erkennen | Zwei Ereignisse können trotzdem dieselbe Geschäftsaktion betreffen |
| Interne Auftrags-/Wirkungskennung | Verhindern, dass dieselbe fachliche Änderung doppelt wirksam wird | Muss zum eigenen Zustand und Mandanten passen |
Schützen Sie den Eingang durch eine verlässliche Eindeutigkeit im Speicher. Speichern Sie außerdem den Bearbeitungszustand. „Schon gesehen“ darf nicht bedeuten, dass ein nach der Annahme abgestürzter Auftrag nie wieder bearbeitet wird. Die Verarbeitung benötigt deshalb einen geregelten Wiederaufnahmeweg.
Prüfen Sie bei der Wirkung erneut die fachliche Zuordnung: Passt das externe Konto zur gespeicherten Integration? Gehört das referenzierte Objekt zu diesem Mandanten? Ist der Zustandswechsel erlaubt? Eine gültige Nachricht eines Partners darf nicht anhand einer frei gelieferten internen Objekt-ID beliebige fremde Datensätze ändern.
Verspätung und fehlende Ereignisse einplanen
Verlassen Sie sich nur dann auf Reihenfolge, wenn der konkrete Vertrag sie für Ihren Verarbeitungsweg zusagt. Stripe garantiert beispielsweise keine Zustellung in Erzeugungsreihenfolge. Ein später eingehendes „angelegt“ darf einen bereits bestätigten Abschluss nicht blind zurücksetzen. Stripe: Event ordering.
Verarbeiten Sie Zustandswechsel daher gegen den aktuellen gespeicherten Zustand und die fachlichen Regeln. Wenn der Anbieter Versionsnummern oder Sequenzen mit passender Bedeutung liefert, können sie helfen. Ein Zeitstempel allein ist ohne entsprechenden Vertrag keine zuverlässige globale Reihenfolge.
Manche Ereignisse sind besser als Anlass für eine authentifizierte Statusabfrage geeignet. Auch dann braucht der Aufruf die richtige Kontozuordnung und die Regeln für externe APIs. Planen Sie einen Abgleich für ausgefallene Zustellungen und dauerhaft offene Aufträge. „Keine Nachricht“ beweist nicht, dass nichts passiert ist.
Schlüsselwechsel und Ausfälle kontrolliert prüfen
Trennen Sie Geheimnisse nach Umgebung und Integration. Bewahren Sie sie außerhalb des Quellcodes auf. Bei einem geplanten Wechsel kann ein befristeter Übergang mit alter und neuer Verifikationsmöglichkeit nötig sein, sofern der Anbieter dies unterstützt. Für ein offengelegtes Geheimnis gilt eine andere Abwägung: Seine weitere Akzeptanz würde gefälschte Nachrichten weiter ermöglichen. Sperrung, Nachlieferung und Ereignisabgleich müssen dann zusammen geplant werden.
Prüfen Sie Ihre Implementierung mit synthetischen signierten Nachrichten: gültiger und veränderter Body, unbekannte Integration, zulässige Wiederholung, Verarbeitung nach Prozessabbruch, vertauschte Zustellreihenfolge und ein voller Eingangspuffer. Wo der Vertrag einen signierten Zeitstempel vorsieht, kommen alte und unzulässig zukünftige Werte hinzu. Der Erfolg ist eine korrekte einmalige fachliche Wirkung im geprüften Fall, kein allgemeines „Exactly once“-Versprechen für verteilte Systeme.
Das HMAC-Beispiel lässt sich rein lokal ohne Netzaufruf prüfen. Es beweist weder die richtige Middleware-Anbindung noch dauerhafte Queueannahme, Replayabwehr oder Anbieterkompatibilität. Diese Punkte benötigen eigene Integrationstests. Eine Rücknahme der neuen Empfängerversion muss bereits angenommene Ereignisse und deren Verarbeitungszustand erhalten.
Der API Security Check prüft diese signierten und zustandsbehafteten Abläufe nicht. Beobachten Sie Signaturfehler, Verzögerungen und offene Ereignisse in Ihrem eigenen Logging und Monitoring; verwenden Sie für doppelte Aufträge zusätzlich den passenden Idempotenzvertrag.
Quellen und Stand
Quellenstand: 27. September 2026. Die Links stehen zusätzlich bei den jeweils begründeten Aussagen.