spinny:~/writing $ less passkeys-webauthn-passwordless-authentication.md
12Hesla jsou jednou z věcí, které jsme normalizovali jen proto, že jsme s nimi léta žili. Uživatelé je zapomínají, znovu je používají, píší je tam, kde by neměli. Týmy musí spravovat resetování, zásady, hashe, úniky, phishing a podporu.34passkey nečiní autentizaci dokonalou, ale odstraňují obrovský problém: server již nemusí udržovat tajemství sdílené s uživatelem.56## Co se skutečně stane78passkey je pověření založené na WebAuthn. Když jej uživatel vytvoří, zařízení vygeneruje pár klíčů:910- soukromý klíč, který zůstává v zařízení nebo ve správci hesel;11- veřejný klíč, který může server uložit.1213Při přihlašování se server nevyptává "řekni mi heslo". Pošlete náhodnou výzvu. Zařízení jej podepíše soukromým klíčem. Server ověří podpis pomocí veřejného klíče.1415To je ta hezká část: pokud je databáze ukradena, nejsou uvnitř žádná hesla k prolomení. A pokud uživatel skončí na falešné doméně, passkey pro tuto doménu neplatí. Není to jen pohodlí, je to konkrétní ochrana proti phishingu.1617## Prohlížeč funguje jako most1819V prohlížeči jsou dvě hlavní API:2021- `navigator.credentials.create()` pro vytvoření passkey;22- `navigator.credentials.get()` pro použití během přihlášení.2324Ale důležitá logika je na serveru. Server musí vygenerovat výzvu, dočasně ji uložit, ověřit odpověď, zkontrolovat zdroj a Relying Party ID, poté vytvořit relaci.2526Klientská část by měla být téměř nudná:2728```typescript29const options = await fetch('/api/passkeys/login/options').then((r) => r.json());3031const credential = await navigator.credentials.get({32 publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(options),33});3435await fetch('/api/passkeys/login/verify', {36 method: 'POST',37 headers: { 'Content-Type': 'application/json' },38 body: JSON.stringify(credential?.toJSON()),39});40```4142Pokud zjistíte, že implementujete šifrování WebAuthn ručně, přestaňte. Použijte robustní knihovnu na straně serveru. Chyby zde nejsou "roztomilé chyby", jsou to autentizační díry.4344## Co uložit do databáze4546Není potřeba zachraňovat půlku světa. Obvykle stačí:4748- ID pověření;49- veřejný klíč;50- připojený uživatel;51- jakékoli ověřovací počítadlo nebo metadata;52- transporty, pokud jsou užitečné pro UX;53- jméno zvolené uživatelem;54- datum vytvoření a poslední použití.5556Minimální tabulka může vypadat takto:5758```sql59create table passkey_credentials (60 id uuid primary key default gen_random_uuid(),61 user_id uuid not null references users(id),62 credential_id text not null unique,63 public_key text not null,64 name text,65 created_at timestamptz not null default now(),66 last_used_at timestamptz67);68```6970Pak bych přidal protokoly auditu a upozornění: pokud někdo vytvoří nový passkey na mém účtu, chci o tom vědět.7172## UX je důležitější než demo7374Demo passkey je vždy krásné: kliknete na Face ID a jste tam. Skutečný produkt je složitější.7576Někdo změní telefon. Někdo používá zamčený firemní počítač. Někteří lidé nechápou, proč prohlížeč navrhuje passkey. Někdo ztratí přístup ke svému zařízení.7778Proto bych nezačínal slovy „od dnešního dne už žádná hesla pro všechny“. Začal bych takto:79801. passkey volitelné pro interní uživatele;812. návrh na vytvoření po úspěšném přihlášení;823. stránka účtu pro přejmenování a odstranění passkey;834. jasný záložní;845. postupné zavádění v hlavním přihlášení.8586Text v rozhraní by měl být jednoduchý. „Použít zamykací obrazovku vašeho zařízení“ je lepší než „ověření pomocí rezidentního pověření FIDO2“.8788## Chyb, kterým bych se vyvaroval8990Nevytvářejte na klienta výzvy. Výzva je vytvořena na serveru a musí být ověřena pouze jednou.9192Nevěřte pouze identifikačnímu dokladu. Musíte ověřit podpis, výzvu, původ a Relying Party ID.9394Neodstraňujte nouzová řešení, dokud nebudete mít dobrý tok obnovy. Passwordless se nemusí stát „pokud ztratíte telefon, jste navždy mimo“.9596Nepovažujte passkey za čistě frontendové tlačítko. Skrytí tlačítka není zabezpečení: skutečné ověření je na straně serveru.9798## Passkey-první nebo passkey-přátelské?99100U nového produktu si můžete myslet passkey-první. U stávající aplikace preferuji přátelské k passkey: přidejte passkey jako doporučenou metodu, měřte úspěch a problémy, pak klidně snižte váhu hesla.101102Ideální migrace není cítit. Uživatel zjistí, že přihlášení je jednodušší, nikoli že společnost změnila svůj ověřovací protokol.103104## Závěr105106passkey jsou zajímavé, protože zlepšují zabezpečení a UX současně, což je vzácné. Nejsou kouzelnou hůlkou: zbývá dobře navrhnout obnovu, kompatibilitu, podporu a zavádění.107108Ale základní změna je silná. Přestaňte žádat uživatele, aby vymýšleli a chránili tajemství. Necháte zařízení podepsat kryptografický důkaz vázaný na vaši doménu. Méně lidské paměti, méně phishingu, méně resetování hesel. Řekl bych, že stojí za to je brát vážně.109110## Zdroje111112- [MDN: Passkeys](https://developer.mozilla.org/en-US/docs/Web/Security/Authentication/Passkeys)113- [MDN: Web Authentication API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API)114- [W3C: Web Authentication](https://www.w3.org/TR/webauthn-3/)115- [passkeys.dev](https://passkeys.dev/)116
:Passkey a WebAuthn: přihlašte se bez hesla, bez magielines 1-116 (END) — press q to close