Weryfikacja dostawy
`verifyWebhookSignature`: porównanie w stałym czasie, okno ochrony przed powtórzeniem i sparsowane zdarzenie w zamian.
W handlerze żądania
Adres URL webhooka jest publiczny. Dowolny host w internecie może wysłać na niego metodą POST JSON o właściwym kształcie, więc handler, który czyta payload.type bez sprawdzenia podpisu, jest otwartym API do zapisu.
import { verifyWebhookSignature } from '@openemail/sdk' export async function POST(request: Request) { try { const event = await verifyWebhookSignature({ payload: await request.text(), headers: request.headers, secret: process.env.OPENEMAIL_WEBHOOK_SECRET!, toleranceSeconds: 300, }) console.log(event.type, event.data) } catch { return new Response('bad signature', { status: 400 }) } return new Response(null, { status: 204 })}Przekazuj SUROWE ciało żądania. Sparsowanie i ponowna serializacja zmieniają kolejność kluczy oraz białe znaki i podpis się nie zgodzi. headers przyjmuje obiekt Headers albo zwykły obiekt, taki jak req.headers w Node, a nagłówek X-OpenEmail-Signature zostanie odnaleziony niezależnie od wielkości liter.
Dwie rzeczy, o które ta funkcja dba, a o które ręcznie pisana weryfikacja zwykle nie: porównuje MAC w stałym czasie, więc poprawnego prefiksu nie da się odtworzyć pomiarem czasu, oraz odrzuca dostawę starszą niż toleranceSeconds w którąkolwiek stronę — domyślnie pięć minut — więc przechwyconego żądania nie da się powtarzać w nieskończoność. toleranceSeconds: 0 wyłącza kontrolę powtórzeń. Oba błędy są ciche. Handler z którymkolwiek z nich przejdzie każdy test, jaki przyszłoby ci do głowy napisać.
Przy każdym niepowodzeniu rzuca wyjątek: brakujący nagłówek X-OpenEmail-Signature, nagłówek w postaci innej niż t=<seconds>,v1=<hex>, znacznik czasu poza oknem albo niezgodny podpis. Po powodzeniu zwraca ciało żądania sparsowane jako WebhookPayload, więc nie ma drugiego JSON.parse, przy którym można się pomylić. Przekaż argument typu, na przykład EmailOpenedData, aby otypować data.
Wymaga globalThis.crypto.subtle, które udostępniają Node 20+, Bun, Deno i Cloudflare Workers.