Hasła to jedna z tych rzeczy, które znormalizowaliśmy tylko dlatego, że żyjemy z nimi od lat. Użytkownicy o nich zapominają, wykorzystują je ponownie, zapisują tam, gdzie nie powinni. Zespoły muszą zarządzać resetowaniem, zasadami, skrótami, wyciekami, phishingiem i wsparciem.
passkey nie czyni uwierzytelnienia doskonałym, ale usuwa ogromny problem: serwer nie musi już zachowywać tajemnicy udostępnianej użytkownikowi.
Co się naprawdę dzieje
passkey to referencja oparta na WebAuthn. Gdy użytkownik go utworzy, urządzenie generuje parę kluczy:
- klucz prywatny, który pozostaje na urządzeniu lub w menedżerze haseł;
- klucz publiczny, który serwer może zapisać.
Podczas logowania serwer nie pyta "podaj mi hasło". Wyślij losowe wyzwanie. Urządzenie podpisuje go kluczem prywatnym. Serwer weryfikuje podpis kluczem publicznym.
To właśnie jest fajne: jeśli baza danych zostanie skradziona, nie będzie w niej żadnych haseł, które można by złamać. A jeśli użytkownik trafi na fałszywą domenę, passkey nie będzie ważne dla tej domeny. To nie tylko wygoda, to konkretna ochrona przed phishingiem.
Przeglądarka działa jak pomost
W przeglądarce dwa główne API to:
navigator.credentials.create(), aby utworzyć passkey;navigator.credentials.get(), aby użyć go podczas logowania.
Ale najważniejsza logika leży na serwerze. Serwer musi wygenerować wyzwanie, zapisać je tymczasowo, zweryfikować odpowiedź, sprawdzić źródło i Relying Party ID, a następnie utworzyć sesję.
Część klienta powinna być prawie nudna:
const options = await fetch('/api/passkeys/login/options').then((r) => r.json()); const credential = await navigator.credentials.get({ publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(options), }); await fetch('/api/passkeys/login/verify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(credential?.toJSON()), });
Jeśli zauważysz, że ręcznie wdrażasz szyfrowanie WebAuthn, przestań. Użyj solidnej biblioteki po stronie serwera. Błędy tutaj nie są „słodkimi błędami”, są to luki w uwierzytelnianiu.
Co zapisać w bazie danych
Nie ma potrzeby ratowania połowy świata. Zwykle wystarczy:
- Identyfikator referencji;
- klucz publiczny;
- podłączony użytkownik;
- dowolny licznik weryfikacyjny lub metadane;
- transporty, jeśli są przydatne dla UX;
- nazwa wybrana przez użytkownika;
- data utworzenia i ostatniego użycia.
Minimalna tabela może wyglądać następująco:
create table passkey_credentials ( id uuid primary key default gen_random_uuid(), user_id uuid not null references users(id), credential_id text not null unique, public_key text not null, name text, created_at timestamptz not null default now(), last_used_at timestamptz );
Następnie dodałbym logi audytu i powiadomienia: jeśli ktoś utworzy nowe passkey na moim koncie, chcę o tym wiedzieć.
UX jest ważniejszy niż demo
Demo passkey jest zawsze piękne: klikasz, Face ID i zaczynasz. Rzeczywisty produkt jest bardziej skomplikowany.
Ktoś zmienia telefon. Ktoś korzysta z zablokowanego komputera firmowego. Niektórzy ludzie nie rozumieją, dlaczego przeglądarka sugeruje passkey. Ktoś traci dostęp do swojego urządzenia.
Dlatego nie zaczynałbym od „od dzisiaj koniec z hasłami dla wszystkich”. Zacząłbym tak:
- passkey opcjonalne dla użytkowników wewnętrznych;
- sugestia utworzenia go po udanym logowaniu;
- strona konta do zmiany nazwy i usunięcia passkey;
- wyraźne wycofanie;
- stopniowe wdrażanie w głównym loginie.
Tekst w interfejsie powinien być prosty. „Użyj ekranu blokady swojego urządzenia” jest lepsze niż „uwierzytelnij się za pomocą danych uwierzytelniających rezydenta FIDO2”.
Błędy, których chciałbym uniknąć
Nie generuj wyzwań dla klienta. Wyzwanie tworzone jest na serwerze i należy je zweryfikować tylko raz.
Nie ufaj tylko identyfikatorowi danych uwierzytelniających. Musisz zweryfikować podpis, wyzwanie, pochodzenie i Relying Party ID.
Nie usuwaj kopii zapasowych, zanim nie uzyskasz dobrego przepływu odzyskiwania. Bez hasła nie musi oznaczać, że „jeśli zgubisz telefon, przepadniesz na zawsze”.
Nie traktuj passkey jako przycisku czysto frontendowego. Ukrywanie przycisku nie zapewnia bezpieczeństwa: prawdziwa weryfikacja odbywa się po stronie serwera.
Passkey-pierwszy czy passkey-przyjazny?
W przypadku nowego produktu możesz najpierw pomyśleć o passkey. W przypadku istniejącej aplikacji wolę przyjazną passkey: dodaj passkey jako zalecaną metodę, mierz sukcesy i problemy, a następnie spokojnie zmniejsz wagę hasła.
Idealna migracja nie jest odczuwalna. Użytkownik odkrywa, że logowanie jest łatwiejsze, a nie, że firma zmieniła protokół uwierzytelniania.
Wniosek
passkey są interesujące, ponieważ poprawiają jednocześnie bezpieczeństwo i UX, co jest rzadkością. To nie jest magiczna różdżka: odzyskiwanie, kompatybilność, wsparcie i wdrożenie muszą zostać dobrze zaprojektowane.
Ale podstawowa zmiana jest silna. Przestań prosić użytkowników o wymyślanie i chronienie tajemnic. Pozwalasz urządzeniu podpisać dowód kryptograficzny powiązany z Twoją domeną. Mniej pamięci ludzkiej, mniej phishingu, mniej resetowania haseł. Powiedziałbym, że warto je traktować poważnie.