spinny:~/writing $ vim passkeys-webauthn-passwordless-authentication.md
1~2Hesla 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.3~4passkey nečiní autentizaci dokonalou, ale odstraňují obrovský problém: server již nemusí udržovat tajemství sdílené s uživatelem.5~6## Co se skutečně stane7~8passkey je pověření založené na WebAuthn. Když jej uživatel vytvoří, zařízení vygeneruje pár klíčů:9~10- soukromý klíč, který zůstává v zařízení nebo ve správci hesel;11- veřejný klíč, který může server uložit.12~13Př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.14~15To 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.16~17## Prohlížeč funguje jako most18~19V prohlížeči jsou dvě hlavní API:20~21- `navigator.credentials.create()` pro vytvoření passkey;22- `navigator.credentials.get()` pro použití během přihlášení.23~24Ale 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.25~26Klientská část by měla být téměř nudná:27~28```typescript29const options = await fetch('/api/passkeys/login/options').then((r) => r.json());30~31const credential = await navigator.credentials.get({32 publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(options),33});34~35await fetch('/api/passkeys/login/verify', {36 method: 'POST',37 headers: { 'Content-Type': 'application/json' },38 body: JSON.stringify(credential?.toJSON()),39});40```41~42Pokud 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.43~44## Co uložit do databáze45~46Není potřeba zachraňovat půlku světa. Obvykle stačí:47~48- 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í.55~56Minimální tabulka může vypadat takto:57~58```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```69~70Pak bych přidal protokoly auditu a upozornění: pokud někdo vytvoří nový passkey na mém účtu, chci o tom vědět.71~72## UX je důležitější než demo73~74Demo passkey je vždy krásné: kliknete na Face ID a jste tam. Skutečný produkt je složitější.75~76Ně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í.77~78Proto bych nezačínal slovy „od dnešního dne už žádná hesla pro všechny“. Začal bych takto:79~801. 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í.85~86Text 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“.87~88## Chyb, kterým bych se vyvaroval89~90Nevytvářejte na klienta výzvy. Výzva je vytvořena na serveru a musí být ověřena pouze jednou.91~92Nevěřte pouze identifikačnímu dokladu. Musíte ověřit podpis, výzvu, původ a Relying Party ID.93~94Neodstraňujte nouzová řešení, dokud nebudete mít dobrý tok obnovy. Passwordless se nemusí stát „pokud ztratíte telefon, jste navždy mimo“.95~96Nepovažujte passkey za čistě frontendové tlačítko. Skrytí tlačítka není zabezpečení: skutečné ověření je na straně serveru.97~98## Passkey-první nebo passkey-přátelské?99~100U 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.101~102Ideá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.103~104## Závěr105~106passkey 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í.107~108Ale 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ě.109~110## Zdroje111~112- [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~
NORMAL · passkeys-webauthn-passwordless-authentication.md [readonly]116 lines · :q to close