Technika · 7. listopadu 2026 · 5 min čtení
Webhooky jednoduše: podpis, opakování, bezpečnost
Co je webhook, jak se liší od dotazu na API a jak zacházet s podpisem, opakováním a duplicitami. S curl a Node.
Webhook je telefonát opačným směrem. Místo aby se váš systém u služby každých pár minut ptal, zda se něco stalo, služba zavolá adresu u vás, jakmile se to stane. Šetří to dotazy a dodává novinky rychleji. Musíte ale zajistit a zabezpečit příjemce. Tento článek vysvětluje obojí.
Webhook, nebo dotaz na API
| Dotaz na API (polling) | Webhook | |
|---|---|---|
| Kdo začíná? | Váš systém | Odesílatel |
| Kdy? | Podle plánu, například každou hodinu | Jakmile nastane událost |
| Náročnost | Dotazy i bez novinek | Nutný dosažitelný příjemce |
| Dobré pro | Reporty, srovnání, doplnění | Upozornění, přeposílání |
| Riziko | Zpoždění do dalšího dotazu | Zpráva se ztratí, pokud příjemce neodpoví |
V praxi mnozí kombinují obojí: Webhook oznámí událost, API podle potřeby stáhne podrobnosti nebo vyplní mezery po výpadku.
Jak probíhá doručení
- Nastane událost, například „platba přijata“.
- Odesílatel pošle POST s JSON na vaši uloženou adresu (HTTPS).
- Váš příjemce ověří podpis, zprávu si poznamená a rychle odpoví kódem z rozsahu 2xx.
- Vlastní práci poté vykoná váš systém.
Krok 3 je důležitý. Stripe v dokumentaci webhooků doporučuje okamžitě vrátit kód 2xx, než se spustí náročná logika, která by mohla vyvolat timeout. Kdo nejdřív zaúčtuje fakturu a teprve pak odpoví, riskuje zbytečná opakování.
Podpis: jak ověřit původ
Vaše adresa je veřejně dosažitelná. Kdokoli by na ni tedy mohl posílat vymyšlené zprávy. Proto seriózní odesílatelé každou zprávu podepisují společným tajemstvím. Obvyklý je HMAC se SHA-256 přes obsah, často spolu s časovým razítkem. GitHub tento postup popisuje takto: HMAC-SHA256 přes obsah, vyjádřený hexadecimálně, s hlavičkou X-Hub-Signature-256. Porovnání má probíhat funkcí s konstantní dobou běhu, aby útočníci nemohli z dob odpovědi nic odvodit.
Důležité body pro vašeho příjemce:
- Použít surový obsah. Podpis počítejte přes přijaté bajty, nikoli přes znovu serializovaný JSON. Už jiný zlom řádku změní podpis.
- Ověřit časové razítko. Stripe používá časové razítko v podpisu a výchozí toleranci pět minut, aby zabránil útokům opakováním. Tolerance 0 kontrolu vypíná.
- Udržet tajemství v tajnosti. Ne v kódu, ne v repozitáři, ale v proměnné prostředí nebo v trezoru.
Zásady open source pro odesílatele a příjemce shrnuje iniciativa Standard Webhooks. Jak konkrétně každý poskytovatel tvoří svůj podpis, je v jeho dokumentaci.
Opakování a dvojí doručení
Pokud váš příjemce neodpoví nebo odpoví chybovým kódem, odesílatel to zkusí znovu. Stripe podle vlastní dokumentace opakuje s rostoucími odstupy až tři dny. Jiní poskytovatelé mají jiná pravidla, někteří webhook po příliš mnoha nezdařených pokusech vypnou. Z toho plyne:
- Počítejte s duplicitami. Táž událost může dorazit vícekrát, i když váš příjemce pracuje správně. Stripe na to výslovně upozorňuje.
- Zpracování udělejte idempotentní. To znamená: Kdo zpracuje tutéž zprávu dvakrát, nevytvoří druhý výsledek. Uložte identifikátor události a známé přeskakujte.
- Nespoléhejte na pořadí. Události mohou přijít prohozené. V případě pochybností ověřte aktuální stav přes API.
Bezpečnost na obou stranách
Pro příjemce: jen HTTPS, kontrolovat podpis a stáří, omezit velikost zprávy, neprovádět příkazy z obsahu. S obsahem zacházejte jako s každým vstupem zvenčí.
Pro odesílatele, kteří volají adresy zákazníků: Kdo nabízí webhooky, volá adresy, které zapsali jiní. To je klasická cesta pro Server-Side Request Forgery. Útočník zapíše interní adresu. Server ji zavolá z chráněné sítě. Popis OWASP uvádí jako cíle například interní služby a adresy metadat cloudových poskytovatelů. Rozumná ochranná opatření:
- povolit jen
https://, - adresu při zápisu i před každým voláním přeložit a odmítnout soukromé, lokální a rezervované rozsahy,
- nesledovat přesměrování slepě,
- nastavit krátké časové limity.
Příklad: odeslat zkušební zprávu pomocí curl
Pomocí curl a openssl můžete svého příjemce otestovat bez skutečného odesílatele. Skript odešle podepsanou zprávu, jakou by poslal odesílatel s časovým razítkem:
GEHEIMNIS="test-geheimnis"
ZEIT=$(date +%s)
INHALT='{"id":"evt_1","typ":"besuch.begonnen","firma":"beispiel-firma.example"}'
SIGNATUR="sha256=$(printf '%s.%s' "$ZEIT" "$INHALT" | openssl dgst -sha256 -hmac "$GEHEIMNIS" | sed 's/^.* //')"
curl -X POST http://localhost:3000/webhook \
-H "Content-Type: application/json" \
-H "X-Zeit: $ZEIT" \
-H "X-Signatur: $SIGNATUR" \
-d "$INHALT"
Příklad: malý příjemce v Node.js
const http = require('http')
const crypto = require('crypto')
const GEHEIMNIS = process.env.WEBHOOK_GEHEIMNIS || 'test-geheimnis'
const gesehen = new Set() // ve skutečnosti: databáze
http.createServer((req, res) => {
if (req.method !== 'POST' || req.url !== '/webhook') { res.writeHead(404); return res.end() }
const teile = []
req.on('data', t => teile.push(t))
req.on('end', () => {
const roh = Buffer.concat(teile).toString('utf8')
const zeit = req.headers['x-zeit'] || ''
const erwartet = 'sha256=' + crypto.createHmac('sha256', GEHEIMNIS).update(zeit + '.' + roh).digest('hex')
const erhalten = String(req.headers['x-signatur'] || '')
const a = Buffer.from(erwartet), b = Buffer.from(erhalten)
const echt = a.length === b.length && crypto.timingSafeEqual(a, b)
const frisch = Math.abs(Date.now() / 1000 - Number(zeit)) < 300
if (!echt || !frisch) { res.writeHead(401); return res.end() }
const ereignis = JSON.parse(roh)
if (!gesehen.has(ereignis.id)) { gesehen.add(ereignis.id); console.log('neu:', ereignis.typ) }
res.writeHead(200); res.end('ok')
})
}).listen(3000)
Příjemce ověřuje podpis a stáří, přeskakuje známé identifikátory a odpovídá okamžitě. Pro provoz potřebujete navíc HTTPS, omezení velikosti a frontu pro další zpracování.
Kde jsou webhooky rozšířené
Platební služby, platformy pro kód a nástroje pro formuláře hlásí události webhookem. Také rozpoznání návštěvníků to umí: Pokud systém ohlásí firmu, která navštívila vaši stránku, přistane přímo v nástroji podle vaší volby. Jak to vede do obchodního systému, ukazuje Jak dostat návštěvy webu do CRM. Alternativu dotazem popisuje Které firmy navštěvují můj web?. Jaká data přitom tečou, vysvětluje Jak funguje rozpoznání firem?.
Časté otázky
Jaký je rozdíl mezi webhookem a API? U API se ptá váš systém, u webhooku se odesílatel ozve sám. Obojí lze kombinovat.
Co se stane, když můj příjemce vypadne? Většina odesílatelů doručení po určitou dobu opakuje. Jak dlouho a jak často, je v dokumentaci poskytovatele. Pro mezery byste měli naplánovat srovnání přes API.
Stačí kontrolovat adresu odesílatele? Ne. Adresy odesílatelů lze předstírat a mění se. Spolehlivý je jen podpis s tajemstvím, které znáte jen vy a odesílatel.