Webhook-Empfänger absichern
Webhooks sind eingehende HTTP-Requests. Wenn Ihr Empfänger keine Authentizität prüft, kann jeder Beliebige Events fingieren. Dieses Tutorial zeigt das Minimum, das Sie tun müssen.
Was Codemeta OS schickt
Jeder Webhook-Request enthält:
- Body: JSON-Payload des Events.
- Header
X-Webhook-Signature: HMAC-SHA256 über den rohen Request-Body. - Header
Content-Type: application/json.
Den HMAC-Schlüssel bekommen Sie beim Anlegen der Webhook-Subscription. Bewahren Sie ihn als Secret auf – idealerweise im Vault Ihres Stacks.
Den rohen Body lesen. Wichtig: Vor dem Parsen. Sobald Ihr Framework den Body als JSON parst und erneut serialisiert, kann das Whitespace-Layout abweichen und die Signatur schlägt fehl.
In Express:
express.raw({ type: 'application/json' })als Middleware vor der Route.Signatur berechnen und vergleichen.
import crypto from 'node:crypto'; function verifyWebhook(rawBody: Buffer, signature: string, secret: string) { const expected = crypto .createHmac('sha256', secret) .update(rawBody) .digest('hex'); // timingSafeEqual schützt vor Timing-Angriffen return crypto.timingSafeEqual( Buffer.from(expected, 'hex'), Buffer.from(signature, 'hex'), ); }Event idempotent verarbeiten. Codemeta OS retryt fehlgeschlagene Auslieferungen. Behandeln Sie also jeden Event mehr als einmal. Speichern Sie die
event.idin Ihrer DB und überspringen Sie Events, die Sie schon gesehen haben.if (await db.events.has(event.id)) return res.status(200).end(); await processEvent(event); await db.events.add(event.id);Mit 2xx schnell antworten. Codemeta OS wartet pro Auslieferung wenige Sekunden auf Ihre Antwort. Tun Sie keine teure Arbeit synchron im Webhook-Handler – nehmen Sie das Event auf, antworten Sie mit 204 No Content, und arbeiten Sie es in einem Hintergrund-Job ab.