CeníkAPI & SMTPŘešeníSrovnáníBlogFAQKontakt
PřihlásitRegistrovat
Tmavý režim
← Zpět na blog
14. října 2026·4 min čtení·Tým TopEmail

Ověřovací kód e-mailem (OTP): délka, expirace, rate limit a kdy radši SMS

Jak správně implementovat jednorázový kód posílaný e-mailem: generování, uložení, platnost, omezení pokusů, text zprávy. A upřímně o tom, kdy je e-mail špatný druhý faktor a kdy sáhnout po SMS.

Šestimístný kód e-mailem je nejlevnější způsob, jak ověřit, že adresa patří člověku, který se registruje, mění heslo nebo potvrzuje platbu. Implementace vypadá triviálně: vygenerovat číslo, poslat, porovnat. Produkční verze má ale pár míst, kde se dá udělat chyba, která buď otevře dveře útočníkovi, nebo zákazníka vyžene. Tohle je kontrolní seznam, který používáme my, a na konci upřímné srovnání se SMS.

K čemu je e-mailové OTP vhodné a k čemu ne

E-mail dokazuje, že uživatel má přístup ke schránce. To stačí pro:

  • ověření adresy při registraci,
  • obnovu hesla (tady je to dokonce standard),
  • potvrzení citlivé změny (nový e-mail, nové platební údaje),
  • přihlášení bez hesla (magic link nebo kód).

Nehodí se jako druhý faktor k heslu, pokud uživatel používá stejné heslo i do e-mailu, což je bohužel častý případ. NIST ve svých doporučeních (SP 800-63B) e-mail jako samostatný druhý faktor neuznává právě proto, že není vázaný na konkrétní zařízení. Pro skutečnou dvoufaktorovou autentizaci použijte TOTP aplikaci, passkey nebo SMS na ověřené číslo.

Generování a formát kódu

  • 6 číslic. Čtyři jsou málo (10 000 kombinací), osm uživatelé přepisují s chybami. Šest je kompromis, který uživatelé znají z bank.
  • Kryptograficky bezpečný generátor: crypto.randomInt(0, 1000000) v Node.js, random_int() v PHP, secrets.randbelow() v Pythonu. Nikdy Math.random() ani rand().
  • Doplnit nuly zleva. Kód 004217 je platný kód, ne chyba.
  • Žádná písmena. Alfanumerické kódy mají víc kombinací, ale uživatel na mobilu přepíná klávesnici a plete O a 0. Bezpečnost řeší rate limit, ne entropie kódu.

Uložení: hash, ne prostý text

Do databáze ukládejte hash kódu (SHA-256 s náhodnou solí stačí; bcrypt je u šestimístného čísla zbytečný), ne kód samotný. Pokud někdo získá přístup k databázi nebo k logům, nemá rovnou platné kódy. K hashi uložte:

user_id, code_hash, purpose, created_at, expires_at, attempts, used_at

purpose je důležitý: kód vydaný pro reset hesla nesmí jít použít pro potvrzení platby.

Platnost a jednorázovost

  • Platnost 5 až 10 minut. E-mail může dojít s malým zpožděním (greylisting, fronta u příjemce), takže 60 sekund jako u SMS je málo. NIST uvádí 10 minut jako horní hranici pro kódy doručované mimo pásmo.
  • Nový kód zneplatní starý. Když uživatel klikne „poslat znovu", starý kód přestane platit. Jinak platí dva a útočník má dvojnásobnou šanci.
  • Jedno použití. Po úspěšném ověření nastavte used_at a kód dál nepřijímejte.
  • Porovnávejte v konstantním čase (hash_equals(), crypto.timingSafeEqual()), aby se podle doby odpovědi nedalo poznat, kolik číslic sedí.

Rate limit: nejdůležitější část

Šest číslic je milion kombinací. Bez omezení pokusů je to pro skript otázka minut. Omezte:

  1. Pokusy na kód: po 5 chybných pokusech kód zneplatněte a vyžádejte nový.
  2. Vydávání kódů na účet: maximálně 3 až 5 kódů za 15 minut. Jinak si útočník může z tlačítka „poslat znovu" udělat nástroj na zahlcení cizí schránky, a vy platíte každý e-mail.
  3. Vydávání kódů z IP adresy: ochrana proti hromadnému zkoušení přes mnoho účtů.
  4. Čekání mezi odesláními: tlačítko „poslat znovu" aktivní až po 30 až 60 sekundách; ukažte odpočet.

Při překročení vracejte stejnou odpověď jako při úspěchu („pokud účet existuje, poslali jsme kód"), aby se podle reakce nedalo zjistit, které adresy jsou registrované.

Text e-mailu

Doručitelnost ověřovacích e-mailů je obvykle výborná (uživatel je čeká), ale pár věcí ji zhorší:

  • Kód do předmětu: 482 913 je váš ověřovací kód pro Muj-eshop.cz. Uživatel ho vidí v notifikaci, nemusí e-mail otvírat. Mezera uprostřed pomáhá čtení.
  • Žádné odkazy a obrázky navíc. Jen kód, pro co platí, jak dlouho, a věta „pokud jste o kód nežádali, ignorujte tento e-mail". Čím míň HTML, tím míň důvodů pro spamový filtr.
  • Neposílejte kód a odkaz zároveň. Vyberte jedno; dva mechanismy jsou dvě útočné plochy.
  • Odesílatel, kterému se dá věřit: overeni@vas-eshop.cz z ověřené domény s DKIM, ne noreply@nejakasluzba.com. Phishingové e-maily vypadají přesně jako OTP, takže vaše musí vypadat správně.
  • Transakční infrastruktura. OTP posílejte přes stejnou cestu jako potvrzení objednávek, ne přes newsletterový nástroj; o rozdílu a oddělení provozu píšeme tady.

Kdy radši SMS

E-mail má jednu slabinu: rychlost není garantovaná. Většina kódů dojde do pár sekund, ale greylisting nebo plná fronta u příjemce udělají z 5 sekund 5 minut, a uživatel mezitím odejde. SMS přes přímé napojení na operátory dorazí typicky do několika sekund a telefon má uživatel v ruce. SMS zvolte, když:

  • uživatel není u e-mailu (potvrzení na pokladně, přihlášení v mobilní aplikaci, kurýr u dveří),
  • potřebujete druhý faktor nezávislý na hesle (schránka může být kompromitovaná stejným heslem),
  • ověřujete telefonní číslo, ne e-mail, třeba kvůli doručení zásilky,
  • jde o platbu nebo změnu s vysokým dopadem, kde cena SMS (u TopSMS.cz od 0,88 Kč) nehraje roli proti škodě.

E-mail zvolte, když ověřujete e-mail, když cena za ověření musí být blízko nule (0,06 Kč u nás proti necelé koruně za SMS), nebo když uživatel sedí u počítače a stejně schránku má otevřenou. Nejlepší řešení pro aplikace s oběma kanály: primárně e-mail, SMS jako záloha, když si uživatel po minutě požádá o kód znovu. Zákazníkům TopSMS nabídneme oba kanály z jednoho účtu, takže přepnutí je otázka jednoho parametru. Praktický návod na SMS OTP včetně kódu najdete na blogu TopSMS.

Shrnutí

  • 6 číslic z bezpečného generátoru, uložit jako hash s účelem.
  • Platnost 5 až 10 minut, nový kód ruší starý, jedno použití.
  • 5 pokusů na kód, limit vydávání na účet i IP, čekání mezi odesláními.
  • Kód v předmětu, minimum HTML, ověřená doména.
  • E-mail pro ověření adresy a obnovu hesla, SMS pro druhý faktor a situace mimo schránku.

Jak posílat ověřovací e-maily přes TopEmail, najdete v přehledu API a SMTP.

OTPbezpečnostimplementaceSMS
Transakční e-maily z vaší domény

Transakční e-maily z vaší domény přes API nebo SMTP, od 0,025 do 0,06 Kč za e-mail podle objemu, prvních 1 000 e-mailů měsíčně zdarma. Registrace zdarma, bez platební karty.

Registrovat zdarma →