Přejít na obsah

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.

Dvě cesty ve srovnání: u dotazu na API se váš systém ptá stále znovu, u webhooku odesílatel jednorázově zavolá vaši adresu, jakmile se něco stane
Grafika: Whovisit · Zobrazit grafiku ve velkém

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émOdesílatel
Kdy?Podle plánu, například každou hodinuJakmile nastane událost
NáročnostDotazy i bez novinekNutný dosažitelný příjemce
Dobré proReporty, srovnání, doplněníUpozornění, přeposílání
RizikoZpoždění do dalšího dotazuZprá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í

  1. Nastane událost, například „platba přijata“.
  2. Odesílatel pošle POST s JSON na vaši uloženou adresu (HTTPS).
  3. Váš příjemce ověří podpis, zprávu si poznamená a rychle odpoví kódem z rozsahu 2xx.
  4. 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.

Číst dále