< Zpět na články

Vítejte ve světě passkeys

Passkeys – možná jste o nich již slyšeli, možná netušíte co jsou. Představím vám, co jsou zač, jak díky nim významně usnadnit ověření uživatelů a zároveň zlepšit bezpečnost nejen autentizace webové aplikace, ale i např. jak snížit SMS OTP náklady. Ukážeme si, jak to celé funguje zvenku i zevnitř. Čeká na vás plně funkční demo s kompletním zdrojovým kódem. Podíváme se, kam se passkeys vyvíjí a co budou brzy umět nového. To celé doplním o vlastní zkušenosti ve snaze vystihnout to podstatné. Pořádný šálek kávy rozhodně přijde vhod, tak tedy vzhůru na to!

Obsah

Kolik vašich hesel bylo prolomeno?

Zkusme se alespoň odpovědi přiblížit. Moje emailová adresa se dle služby haveibeenpwnded.com nachází ve 24 únicích dat. V mnoha z nich společně s heslem a dalšími citlivými daty. Zlobit se na nedokonalou implementaci dané služby můžeme, ale svět bezpečnosti je proměnlivý a co platilo za bezpečné před pár lety, dnes může sloužit jako falešná jistota bezpečí. Je to svět plný pravděpodobností a kalkulovaných rizik, kde se spoléháme, že ani nejvýkonnější počítat za x let nebude schopen prolomit bezpečnostní vrstvu naší aplikace.

Schválně si ověřte, jak dlouho by trvalo prolomit obdobné heslo tomu vašemu, správce hesel Bitwarden nebo NordPass vám udělají odhad. Je třeba ho samozřejmě brát s rezervou, ale pro hrubou představu to není vůbec špatné.

Problém je, že i když si zvolíte heslo, které potrvá prolomit tak dlouho, že i Slunce tou dobou už bude dávno vyhaslé, nezabráníte možnosti, že si útočník nenajde jinou cestu, jak získat přístup k vašemu účtu. Např. se můžete stát součástí phishing útoku a heslo útočníkovi můžete sdělit omylem vy sami. V domění, že se přihlašujete do vaší staré známé aplikace, vyplníte svoje přihlašovací údaje a nepatrně jiné URL adresy si všimnete, až když už je pozdě.

Ať už by útočník k heslu mohl přijít jakkoliv, je lepší mít navrženou bezpečnostní vrstvu tak, že ani uniklé heslo, neprolomí přístup do vašeho účtu. Jak? Právě díky více-faktorovému ověření uživatele, konkrétně jak zmiňuje OWASP:

💡
Co je MFA?

MFA je ověření uživatele alespoň dvěma faktory, které můžeme rozdělit do tří hlavních kategorií:

  • něco, co víte: heslo, PIN, bezpečnostní otázka, …
  • něco, co máte:
    • chytrý telefon:
      • pro příjem jednorázového (SMS) kódu (OTP – one-time-password)
      • pro vygenerování časově-jednorázového kódu pomocí aplikace jako je Google Authenticator (TOTP – time-based one-time-password)
    • USB bezpečnostní klíč
  • něco, co jste: biometrické ověření (otisk prstu, rozpoznání obličeje)

V citaci výše OWASP dokonce zmiňuje právě FIDO2 passkeys, jako možnou řešení MFA, která je uživatelsky přívětivější než stávající metody.

Co jsou tedy passkeys?

Zjednodušeně řečeno se jedná o snadnější a bezpečnější způsob, jak ověřit uživatele. Místo hesla je možné použít např. otisk prstu nebo rozpoznání obličeje, záleží na typu autentizátoru, který vaše zařízení podporuje.

Koneckonců zkuste si to sami, zde je plně funkční demo, přes které lze passkey vytvořit a pak se s ním znovu přihlásit do aplikace:

🖼️ Demo: with-webauthn.dev

👨‍💻 Zdrojový kód: github.com/cermakjiri/with-webauthn

Co jsou FIDO2 passkeys?

FIDO2 (Fast IDentity Online 2) je sdílený projekt mezi FIDO Alliance a W3C (World Wide Web Consoritum) s hlavním cílem vytvořit nový soubor bezpečných standardů pro ověřování identity uživatelů na webu. Místo ověření uživatele pomocí uživatelsky vytvořeného hesla, daný autentizátor:

  • Vygeneruje kryptograficky provázaný pár klíčů.
  • Privátní klíč podepíše challenge vygenerovanou vaším serverem (tzv. relying party).
  • Autentizátor vrátí veřejný klíč a podpis*, tedy public-key credential nebo-li populárně řečeno passkey.
  • Privátní klíč není sdílen, zůstává v autentizátoru**.

*Autentizátor, kromě veřejného klíče a podpisu, vrátí mnoho dalších informací, které probereme níže v kapitole: Jak vytvořit nový passkey.

**To platí jen pro tzv. device-bound passkeys. Podrobněji rozebráno později.

Konkrétně, FIDO2 má dvě základní složky:

  1. Client to Authenticator Protocol 2 (CTAP2) – komunikační protokol mezi kryptografickým autentizátorem (jako je např. FaceID, TouchID, nebo hardwarový bezpečnostní klíč) a klientem (např. user agent).
  2. W3C Web Authentication (WebAuthn)API dostupné v prohlížeči, přes které inicializovat vytvoření a použití takového passkey.

WebAuthn API nabízí momentálně “pouze” dvě metody:

  • navigator.credentials.create(...): Vytvoří passkey během tzv. attestation ceremony.
  • navigator.credentials.get(...): Získá passkey během tzv. assertion ceremony.

Kombinaci parametrů, které přijímají, je opravdu veliká. W3C WebAuthn specifikaci můžete nalézt zde, přístupněji to pokrývá MDN nebo Google Developers.

Jak vytvořit nový passkey?

Zavoláním navigator.credentials.create(...) metody vytvoříme nový passkey, procesem zvaným jako attestation ceremony:

Detailnější proces vytvoření passkey:

  1. Klient pošle API request na server s uživatelským jménem.

  2. Server vygeneruje challenge společně s dalšími povinnými parametry:

    • pubKeyCredParams (COSEAlgorithmIdentifier)
      • Pole asymetrických algoritmů pro vytvoření podpisu, které váš server (relying party) podporuje. Ne každý autentizátor může podporovat všechny asymetrické algoritmy, proto je dobré ji uvést co nejvíce. Kompletní seznam zde.
        💡
        Pokud budete požadovat použití algoritmu, který daný autentizátor neumí, dostanete tento error, který není lehké zpětně odůvodnit:
        DOMException: The operation either timed out or was not allowed. See: https://www.w3.org/TR/webauthn-2/#sctn-privacy-considerations-client.
    • rp (relying party): Doména v jaké bude možné použít passkey.
    • user:
      • id: Base64 URL formát
      • name: uživatelské jméno, např. email
      • displayName: jméno uživatele
    • challenge: Base64 URL formát
  3. Server zároveň vygeneruje session ID (např. jako serve-side cookie). Pod tímto ID uloží do databáze vygenerovanou challenge a další údaje, které budou potřeba při ověření výsledku autentizátoru.

  4. Klient převede hodnoty z Base64 URL na TypedArray a celou strukturu pošle do navigator.credentials.create:

  1. Klient z attestationResponse získá public-key, typy přenosu, použitý algoritmus pro podpis a další informace AuthenticatorAttestationResponse. Vše pošle na server k ověření.
  2. Server podle session ID najde v databázi očekávanou challenge a ostatní uložené údaje. Zkontroluje zda session neexpirovala a provede validaci AuthenticatorAttestationResponse.

Ze zkušenosti, mohu říct, že parsování AuthenticatorAttestationResponse není vůbec snadné. Ku příkladu je nutné se popasovat s dekódování CBOR formátu – binární datová reprezentace, kterou si lze představit jako JSON ale pro komunikaci s autentizátory – a následně dodržet všechny podmínky korektní validace. Proto může být vhodnější použít nějakou ověřenou knihovnu, která to udělá za nás, např. SimpleWebAuthn.

💡
WebAuthn SDK

V demu používám právě SimpleWebAuthn, jak na klientovi tak serveru. Nicméně alternativ je mnoho, včetně knihoven v jiných jazycích: awesome-webauthn.


🧑‍💻
Zdrojový kód

Vytvoření passkey (registrace): server a klient.

Důležité poznatky k vytvoření passkey:

  • Passkeys jsou provázané s doménou vaší aplikace (tedy podle rpId). Pokud se změní, vytvořené passkeys se stanou neplatnými:
    • Passkey vytvořený s rpId: 'example.com' je možné použít na https://example.com, nikoliv na https://subdomain.example.com.
    • Passkey vytvořený s rpId: 'subdomain.example.com' lze použít na https://subdomain.example.com a také na https://example.com
    • Tedy platí, že passkeys lze použít na doméně stejného nebo vyššího řádu.
    • Pokud potřebuje řešit podporu na různých doménách, existuje experimentální funkce related origins (viz kapitola Jak je to s podporou v prohlížečích).
  • Uživatelské jméno nemusí být email, ale může to být vhodná volba. Pokud máte více tzv. authentication providers, pak email může posloužit k jejich propojení. Nebo také z toho důvodu, že v kombinaci s autocomplete="email" a funkcí služby typu iCloud+, která vytvoří anonymní email a přeposílá zprávy na uživatelův původní email. Lze tím uživateli pomoc zjednodušit a zabezpečit registrační proces (při úniku dat, unikne pouze alias, nikoliv skutečná emailová adresa).
  • Pokud chceme zabránit vytvoření více passkeys pro danou službu na jednom autentizátoru pro stejného uživatele (což nejspíš chceme), je třeba vyplnit excludeCredentials s existujícími passkeys, které jsme si uložili do databáze.
  • challenge:

Typy autentizátorů

Aktuální verze WebAuthn API umí komunikovat s celou řadou kryptografikých autentizátorů, které dělíme na:

  1. Platform authenticators: Umístěné v zařízení: biometrické senzory, PIN, pattern.
  2. Roaming (cross-platform) authenticators: Připojitelné pomocí USB, bluetooth, NFC, či jejich kombinací.

WebAuthn API:

Platform authenticator:

Platform authenticator

Roaming (cross-platform) authenticator:

Roaming (cross-platform) authenticator

Bez specifikovaného typy:

Roaming (cross-platform) authenticator

Konkrétní UI se může lišit v závislosti na operačním systému a prohlížeči. Zde jsou ukázky z Mac OS, Chromium.


Jak použít stávající passkey?

Zavoláním navigator.credentials.get(...) metody získáme existující passkeys, procesem zvaným jako assertion ceremony.

Ilustruji zde tři variace použití: První je přihlášení uživatele do aplikace, druhá je ověření uživatele v aplikaci, který je již přihlášen (tj. např. před provedením citlivé akce, kde chceme mít jistotu uživatelské přítomnosti) a třetí ukazuje přihlášení do aplikace pomocí tzv. passkeys autofill.

  1. Přihlášení uživatele do aplikace (minimální flow):

    Nevyžaduje žádné username, ani seznam existujících passkeys, stačí challenge vygenerovanou vaší relying party a prohlížeč nabídne seznam všech passkeys pro aktuální doménu – takovéto passkeys nazýváme discoverable credentials (dřívější terminologií resident keys):

    Proces použití passkey:

    1. Server vygeneruje challenge:
    2. Obdobně jako při vytvoření passkey, server vygeneruje session ID (např. jako serve-side cookie). Pod tímto ID uloží do databáze vygenerovanou `challenge` a další údaje, které budou potřeba při ověření výsledku autentizátoru.
    1. Klient převede challenge na TypeArray a zavolá get methodu:
    1. Uživateli se zobrazí seznam všech dostupných passkeys pro danou službu:
      List of discoverable credentials
    🧑‍💻
    Zdrojový kód

    Login: server a klient.

  2. Ověření přihlášeného uživatele: Před provedením citlivé akce specifikujeme passkey, pod kterým je uživatel již přihlášen – vyžadujeme znovu-ověření uživatele:

    1. Server kromě challenge vrátí i daný passkey (allowCredentials) – tj. passkey id a typy (transports), jakými lze připojit daný autentizátor:

    2. Opět, server vygeneruje session ID (např. jako serve-side cookie). Pod tímto ID uloží do databáze vygenerovanou challenge a další údaje, které budou potřeba při ověření výsledku autentizátoru.

    3. Jelikož se jedná o citlivou akci, nastavíme userVerification: 'required':

      A ještě podstatnější je zkontrolovat assertionResponse, že autentizátor skutečně provedl user verification. Viz kapitola Co je user presence & user verification?

    4. Uživateli se přímo zobrazí ověření pro daný passkey:

      User is prompted to authenticate himself/herself.
      🧑‍💻
      Zdrojový kód

      Odstranění passkey s znovu-ověřením uživatele: server a klient.

  3. Passkey autofill: Nebo-li conditional mediation (conditional UI) je možnost, jak zlepšit UX přihlášení pomocí passkeys. Uživateli jsou, podobně jako v první ukázce použití passkey, nabídnuty všechny dostupné (discoverable) passkeys, v tomto případě ale v rámci select input options:

    Passkeys autofill
    1. Server tentokrát nevrací žádné allowCredentials:

    2. Klient musí specifikovat mediation parametr:

    3. Zároveň musí u daného HTML prvku nastavit autocomplete="webauthn ..." atribut:

    🧑‍💻
    Zdrojový kód

    Passkeys autofill: server a klient.

Důležité poznatky k použití passkey:

  • Zavolání navigator.credentials.get(...) musí proběhnout, co nejdříve, po načtení stránky – než uživatel klikne do daného inputu.

  • V rámci passkeys autofill se používá také navigator.credentials.get(...). V tomto případě ale vrací Promise, který se dostane do stavu resolved, až když uživatel vybere nějaký z nabízených passkeys.

    Což také známené, že pokud uživatel žádný passkey nevybere a klikne na tlačítko přihlásit, aplikace znovu zavolá navigator.credentials.get(...) a dostanete error: OperationError: A request is already pending. Je proto nutné předchozí požadavek nejprve zrušit pomocí AbortController API:

  • userHandle v assertionResponse odpovídá user ID vygenerované při attestation ceremony (při vytváření passkey) – MDN docs. Může se hodit pro zjednodušení přihlašovacího procesu. User ID je sice nullable, ale musí být vždy definovaný pro discoverable credentials.


💡
Co je user presence & user verification?

Nejzákladnější forma ověření uživatele je tzv. user presence (UP flag) – uživatel pouze stiskne tlačítko na svém autentizátoru, např. na USB bezpečnostním klíči, a tím potvrdí svoji přítomnost.

Oproti tomu user verification (UV flag) vyžaduje ověření uživatele, podle možnosti autentizátoru: tj. PIN, otisk prstu, gesto, apod. Díky tomu server (relying party) může určit, zda se jedná o stejného uživatele, avšak nikoliv určit přesnou identifikaci uživatele.

Daný autentizátor výsledky UP i UV zakóduje, společně s ostatními boolean hodnotami (flags), do Authenticator Data.

Server (relying party) následně tyto flags projde a určí, zda byl uživatel ověřen či nikolivkompletní seznam podmínek ověření pro assertion ceremony.

Z pohledu klienta (relying party), tedy parametrů poslané do get a create metod, lze pouze vyslovit přání, jak moc má autentizátor vyžadovat ověření uživatele:

userVerification: UserVerificationRequirement

  • required: Relying party požaduje UV a značí je pokud se uživatel neprokáže, operace selže.
  • preferred (výchozí): Relying party preferuje provést UV. Operace ale neselže, pokud to možné není.
  • discourage: Relying party preferuje přeskočení UV.

Ze zkušenosti, použití hodnoty discourage na Mac OS, nemá žádný efekt na Touch ID. Po uživateli je vždy požadován otisk prstu.

Hlubší rozbor lze nalézt na web.dev – userVerification deep dive nebo přímo oficiální WebAuthn specifikaci.

Kolika faktorové je ověření pomocí passkeys?

Všechny WebAuthn autentizátory splňují kategorii něco, co máte. Pokud navíc podporují user verification, jedná se o více-faktorové autentizátory. Tedy autentizátory podporující PIN, splňují faktor něco, co víte a biometrické autentizátory zase něco, co jste.

Synchronizace & mazání passkeys

Na začátku jsem v rámci popisu vytvoření passkey napsal, že privátní klíč zůstává bezpečně uložen v autentizátoru. Toto tvrzení se po zkušenosti s passkeys nezdá moc pravdivé. Koneckonců už v rámci dema jste si mohli všimnout, že pokud vytvoříte nový passkey, je vám nabídnuto uložení do iCloud klíčenky a jejich alternativám na jiných OS, resp. prohlížečích:

Uložení passkey do iCloud klíčenky.
Oproti tomu pokud jste zvolili uložení např. přímo do prohlížeče:
Uložení passkey pouze na zařízení, kde bylo vytvořeno.

Podle toho, kde je uložen privátní část, dělíme passkeys na:

  1. Synced passkey: public-key credential, jehož privátní klíč může být přenes mimo zařízení původu. Pokud použijete Touch ID, Face ID bude se jednat vždy o passkey. Passkeys existují až od verze WebAuthn 3. Je to sice kompromis mezi bezpečností a použitelností, ovšem právě díky tomu dochází k široké adopci WebAuthn. V demu ho pak uvidíte jako:

    Synced passkey
  2. Device-bound passkey: public-key credential, jehož privátní klíč zůstává uložen v zařízení původu. Jedná se bezpečnější způsob použití WebAuthn než passkey, ale pokud z principu definice nelze daný public-key credential obnovit. Takovýto public-key credential bude vytvořen, např. pokud zvolíte uložení do prohlížeče nebo máte k dispozici USB security key (např. Trezor nebo Yubikey). V demu ho pak uvidíte jako:

    Device-bound passkey

A co na to WebAuthn specifikace?

WebAuthn 3 nově oproti WebAuthn 2 nabízí možnost přenést privátní klíč (resp. celý credential public key source) mimo zařízení původu, ale už nespecifikuje, jak k tomu má dojít.

Pokud jste dříve přišli o daný autentizátor, ztratili se všechny passkeys nadobro. Tomuto šlo předejít pomocí registrování více autentizátorů. Ovšem vytváření právě takových záloh, není moc uživatelsky přívětivé. Tento problém je nyní vyřešen právě díky sync-passkeys, které jsou uložené typicky různých cloudových klíčenkách, podle toho jakou platformu používáte – iCloud klíčenka, Google Password Manager a údajně někdy brzy i Windows Hello.

Je to bezpečné? V rámci Apple ekosystému:

  • Privátní klíč je přenesen na cloud přes kanál s koncovým šifrováním.
  • K přenosu a uložení je použita AES šifra s délkou klíče 256 bitů (od iOS 12).
  • K uložení do iCloud je nutné mít u Apple účtu nastavené 2-faktorové ověření.

Pokud se vám varianta přesunutí passkeys na cloud nezamlouvá, stále existuje možnost si pořídit fyzický bezpečnostní klíč a zachovat si tak plnou kontrolu nad místem úložiště.

💡
Jak rozeznáme synced od deviced-bound passkeys?

Postup je obdobný jako při získání user presence (UP) a user verification (UV) flags, který jsem popisoval výše v rámci assertion ceremony. Zde místo bitu na pozici 0 (odpovídající UP) a bitu na pozici 2 (odpovídající UV), potřebujeme:

Bit na pozici 3 s hodnotou pro Backup Eligibility (BE) flag. Tato hodnota nám říká, zda je možné přenést zdroj passkey (tedy privátní klíč a další data) mimo autentizátor, kde byl daný privátní klíč vygenerován.

  • Typ přenosu nemusí být pouze na cloud, ale i manuálním importem/exportem, přes lokální sít nebo např. peer-to-peer synchronizace. Alespoň tak zní specifikace.
  • Pokud se jedná přenositelný passkey, nazýváme ho multi-device credential, v opačném případě se jedná o single-device credential.
  • Tuto informaci získáme během vytvoření passkey – attestation ceremony.

Bit na pozici 4: Backup State (BS): Byl už zdroj passkey přenesen?

Authenticator data

Kompletní parsování dat autentizátoru umí provést již zmíněná SimpleWebAuthn. Klient jen odpověď z autentizátoru pošle na sever, kde zavolá:

Pro nadšence bitové manipulace, CBOR formátu a znalosti jiných low-level pojmů, přikládám funkci této knihovny na parsování authenticator data – parseAuthenticatorData.ts.


Umí nám WebAuthn poskytnout kryptografický důkaz o původu autentizátoru a tedy co je a kdy není attestation? Jak poznat na jakém autentizátoru byl passkey vytvořen? 👇

💡
Co je attestation a jak souvisí s AAGUID?

Authenticator Attestation Globally Unique Identifier (AAGUID) je 128-bitový identifikátor typu (tj. značky, modelu) autentizátoru. Je zvolen výrobcem a měl by být unikátní napříč všemi autentizátory.

WebAuthn attestation je důkaz, že autentizátor opravdu pochází od daného výrobce. Tento důkaz si můžeme kryptograficky ověřit díky tzv. chain of trust a můžeme tedy bezpečně tvrdit, zda podpis pochází z řetězce certifikátů započatým tzv. root certifikátem či nikoliv.

Ve výchozím nastavení create metoda nepoužije tento způsob ověření. Je proto vhodné upravit attestationType:

SimpleWebAuthn tohle zvládne udělat za nás (pokud je tedy attestationType: 'direct') a podle fmt (attestation statement format) automaticky vybere odpovídající root certifikát. Pro pokročilejší použití nabízí i SettingsService třídu se kterou lze nastavit vlastní root certifikát nebo ověřit aktuálně použitý. Výchozí root certifikáty, které používá naleznete zde, což si můžete porovnat s oficiálním root certifikátem např. firmy Apple.

Projekt passkey-authenticator-aaguids seskupuje soubor všech dostupných autentizátorů (název, logo, atd.), což se může hodit při vytváření UI registrovaných passkeys uživatele.

Důležité poznatky:

  • Některé platformy, které implementovali synced passkeys, nepodporují attestation. Tedy i když nastavíte attestationType: 'direct', vrátí vám autentizátor výsledek, kde fmt je null.

    • Toto aktuálně platí pro Apple:

    • Také pro Android:

    • Aktuálně, Windows Hello údajně naopak podporuje pouze bound-device passkeys, tedy i attestation (Window 11). Výhledově ale plánuje implementaci synced passkeys a uživatel by měl tedy možnost si vybrat.

Jak passkey smazat?

WebAuthn API nabízí metody create a get, ale co delete? Momentálně nic takové dostupné není.

Passkey se skládá z veřejné části, uložené v databázi naší aplikace a privátní časti, uložené v cloudu, autentizátoru či jiných místech. Z pohledu naší aplikace lze provést smazání této veřejné části z databáze a omezit nabízené passkeys při přihlášení pomocí allowCredentials parametru. Dále můžeme uživateli ilustrovat (podle platformy, resp. AAGUID), jak může odstranit privátní část, viz How to Delete a Passkey on Apple, Windows and Android.

Bude to lepší? Na tento nedostatek cílí WebAuthn Signal API z nová verze WebAuthn specifikace.

O co tedy jde? Cílem je, aby relying parties mohli hlásit informace o zrušených nebo prostě jen nesprávných passkeys (např. se při změně uživatelského jména). Tato komunikace má být dostupná skrz nové metody:

  • Smazání passkey (oficiální návrh API):

  • Smazání mnoha passkeys oznámením všech přijímaných passkeys (oficiální návrh API):

  • Změna detailů uživatele (oficiální návrh API):

Je to hudba budoucnosti, uvidíme, jak blízké. Aktuálně si to lze vyzkoušet v Chrome Canary, viz oficiální demo.


Jak je to s podporou v prohlížečích?

Jedná o široce adoptovanou technologii napříč platformami. Je ale dobré podotknout, že Windows Hello aktuálně podporuje pouze bound-device passkeys, synced passkeys prý přijdou brzy.

Stabilní funkce:

FunkceChromeEdgeFirefoxSafariZdroj
🟢 Základní WebAuthn API67186013MDN
🟢 Autentizátoru podporující ověření uživatele67186013MDN
🟢 Passkeys autofill10810811916MDN
Aktuální verze13113013318

Chystající se funkce:

FunkceChromeEdgeFirefoxSafari
🟡 Related origins128128Unknown stand.18
⚪ WebAuthn Signal APICanaryUnknown stand.No public comments.Positive stand.

Bezpečnostní rizika & soukromí uživatelů

Odhalení nechráněných účtů

Představme si situaci, máme přihlášení pomocí klasického uživatelského jména a hesla. Zároveň nekteří uživatelé mají jako nastavený přihlášení pomocí passkey. Útočník zkouší různá uživatelská jména, relying party vrátí existující passkeys (tedy jejich IDs a způsob přenosu) v allowCredentials argumentu nebo vyhodí error, pokud pro daný účet neexistují žádný passkeys. V obou případech, může útočník detekovat, které účty jsou nechráněné pomocí WebAuthn a které tak můžou být slabší na prolomení.

Jak se tomu bránit?

Řešením může být např. vyplňovat allowCredentials vždy, ať už pravými nebo pseudo-náhodnými hodnotami deterministicky odvozenými z uživatelského jména. Pro uživatel se nic nezmění, autentizátor nabídne pouze validní passkeys. Další variantou je použití výhradně discoverable credentials a tedy nastavit allowCredentials: [], což zároveň brání i potencionální de-anonymizaci přes passkey IDs.

Zároveň může být lepší nevracet ze serveru specifické chyby napovídající útočníkovi (ano, je to balance mezi UX a bezpečnostní).

Zdroj: w3c.github.io

Detekce existujících účtů

V případě, že je email použit jako uživatelské jméno při registraci uživatele a abychom předešli situaci, kdy útočník může zjistit, zda daný email má uživatel vytvořený účet, může být vhodné, nejprve zaslat na danou emailovou adresu jednorázový kód. Tím ověřit, že ji uživatel skutečně vlastní a teprve pak pokračovat s vytvořením passkey.

Zdroj: w3c.github.io

Více ohledně bezpečnosti a soukromí passkeys můžete najít v oficiální WebAuthn specifikaci.


Stojí za to jít do toho?

I když to nejspíš není z tohoto článku patrné, osobně jsem z této technologie opravdu nadšený. Po dlouhé době vidím webovou technologii, která reálně dokáže zlepšit produkt pro koncové uživatele a při správné implementaci, významně zlepšit bezpečnost i usnadnit autentizaci.

Pokud stále nevěříte, že passkeys dokáží zlepšit váš produkt:

A jestli už přemýšlíte, jak provede integraci passkeys do svého produktu, mohu doporučit:

Pro vývojáře:

Zároveň, prosím, berte v potaz, že se jedná o velmi dynamicky se rozvíjející technologii. Tudíž i přes snahu vše popsat co nejpřesněji, se některé informace mohou stát brzy zastaralé.

Děkuji vám za pozornost, budu rád za váš názor. Pokud si nechcete nechat ujít moje další příspěvky, nejen o passkeys a WebAuthn, sledujte mě na LinkedIn (no spam – moje aktivita je toho důkazem).


Další zdroje

Jiří Čermák
Jiří Čermák
Frontend Tech LeadJirka rád dělá věci pořádně a když už mu z toho hlava leze kolem, jde si zalézt na stěnu. Miluje tracky přírodou, jazz a knížky.

Máte zájem o spolupráci? Pojďme to probrat osobně!

Napište nám >