Kako rade potpisi webhookova
Webhook je samo HTTP POST sa tuđeg servera, a svako može da pošalje POST na vaš URL. Da bi dokazali da zahtev dolazi od provajdera, oni računaju HMAC nad telom sa tajnom koju znate samo vas dvoje i šalju ga u zaglavlju. Vi ga ponovo računate i poredite. Tajna nikada ne putuje; putuje samo heš.
Zašto se dešava „invalid signature“
- Heširali ste parsirano telo, a ne sirove bajtove. Frejmvorci koji parsiraju JSON pre nego što se vaš handler pokrene (Express sa
express.json(), Rails, Django) daju vam objekat; njegova ponovna serijalizacija menja beline i redosled ključeva i heš se više ne poklapa. Uhvatite sirovo telo. - Pogrešna tajna. Stripe ima drugačiji
whsec_po endpointu i po okruženju; GitHubova tajna je po webhooku; Slackov signing secret nije bot token. - Provajder potpisuje više od tela. Stripe potpisuje
timestamp.body; Slack potpisujev0:timestamp:body; Svix potpisujeid.timestamp.body; Twilio potpisuje URL plus sortirana polja forme. Recept za svaki se prikazuje iznad kad ga izaberete. - Kodiranje. Neki provajderi šalju heks, neki Base64; neki dodaju prefiks
sha256=. Uporedite oblike. - Proksiji. Proksi ili CDN koji ponovo kodira telo (gzip, charset) ili ograničenje veličine tela koje ga seče pokvariće heš.
Bezbedno poređenje
U produkciji poredite funkcijom konstantnog vremena (crypto.timingSafeEqual, hmac.compare_digest, hash_equals) i proverite da je vremenska oznaka sveža (Stripe i Slack dozvoljavaju pet minuta) da sprečite replay. Ova stranica je debager, a ne referentna implementacija; koristi obično poređenje jer timing napadi na vaš sopstveni pregledač nisu briga.
Pitanja
Da li je moja tajna ovde bezbedna?
HMAC se računa u vašem pregledaču preko WebCrypto i stranica ne pravi mrežne zahteve. Ipak, koristite tajnu test endpointa i rotirajte sve što nalepite u veb stranicu ako želite da budete strogi.
Zašto GitHub šalje i X-Hub-Signature i X-Hub-Signature-256?
Prvi je HMAC-SHA1, zadržan za stare integracije; drugi je HMAC-SHA256 i njega treba proveravati. Oba su nad sirovim telom sa istom tajnom.
Očekivana vrednost se poklapa osim po velikim/malim slovima. Da li je to neuspeh?
Heks ne razlikuje velika i mala slova u kodu za proveru svakog provajdera, pa ne; i ovaj alat heks poredi bez obzira na veličinu slova. Base64 razlikuje velika i mala slova.
Stripe kaže da je vremenska oznaka prestara.
Stripeove biblioteke odbijaju potpise čiji je t= udaljen više od 300 sekundi od trenutnog vremena, da bi sprečile replay. Ponovno slanje uhvaćenog zahteva kasnije neće uspeti iz tog razloga iako je HMAC ispravan; alat beleži starost.