Lösenord Àr en av de saker som vi har normaliserat bara för att vi har levt med dem i flera Är. AnvÀndare glömmer dem, ÄteranvÀnder dem, skriver dem dÀr de inte borde. Team mÄste hantera ÄterstÀllningar, policyer, hash, lÀckor, nÀtfiske och support.
passkey gör inte autentisering perfekt, men de tar bort ett stort problem: servern behöver inte lÀngre hÄlla en hemlighet som delas med anvÀndaren.
Vad hÀnder egentligen
En passkey Àr en legitimation baserad pÄ WebAuthn. NÀr anvÀndaren skapar den genererar enheten ett nyckelpar:
- en privat nyckel, som finns kvar pÄ enheten eller i lösenordshanteraren;
- en publik nyckel som servern kan spara.
NÀr du loggar in frÄgar servern inte "berÀtta lösenordet". Skicka en slumpmÀssig utmaning. Enheten signerar den med den privata nyckeln. Servern verifierar signaturen med den publika nyckeln.
Det Àr det fina: om databasen blir stulen finns det inga lösenord inuti att knÀcka. Och om en anvÀndare hamnar pÄ en falsk domÀn Àr passkey inte giltig för den domÀnen. Det Àr inte bara bekvÀmlighet, det Àr ett konkret skydd mot nÀtfiske.
WebblÀsaren fungerar som en brygga
I webblÀsaren Àr de tvÄ huvudsakliga API:
navigator.credentials.create()för att skapa en passkey;navigator.credentials.get()för att anvÀnda den under inloggning.
Men den viktiga logiken ligger pÄ servern. Servern mÄste generera utmaningen, spara den tillfÀlligt, verifiera svaret, kontrollera kÀllan och Relying Party ID, sedan skapa sessionen.
Klientdelen borde vara nÀstan trÄkig:
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()), });
Om du kommer pÄ att du implementerar WebAuthn-kryptering för hand, sluta. AnvÀnd ett robust bibliotek pÄ serversidan. Felen hÀr Àr inte "söta buggar", de Àr autentiseringshÄl.
Vad ska sparas i databasen
Det finns ingen anledning att rÀdda halva vÀrlden. Vanligtvis nog:
- ID för legitimationen;
- offentlig nyckel;
- ansluten anvÀndare;
- alla verifieringsrÀknare eller metadata;
- transporter, om anvÀndbara för UX;
- namn valt av anvÀndaren;
- Skapandedatum och senaste anvÀndning.
En minimal tabell kan se ut sÄ hÀr:
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 );
Sedan skulle jag lÀgga till granskningsloggar och aviseringar: om nÄgon skapar en ny passkey pÄ mitt konto vill jag veta om det.
UX betyder mer Àn demo
Demon av en passkey Àr alltid vacker: du klickar, Face ID, du Àr med. Den faktiska produkten Àr mer komplicerad.
NÄgon byter telefon. NÄgon anvÀnder en lÄst företagsdator. Vissa mÀnniskor förstÄr inte varför webblÀsaren föreslÄr en passkey. NÄgon förlorar Ätkomst till sin enhet.
Det Àr dÀrför jag inte skulle börja med "frÄn och med idag inga fler lösenord för alla". Jag skulle börja sÄ hÀr:
- passkey valfritt för interna anvÀndare;
- förslag att skapa en efter en lyckad inloggning;
- kontosida för att byta namn och ta bort passkey;
- klara fallback;
- gradvis utbyggnad i huvudinloggningen.
Texten i grÀnssnittet ska vara enkel. "AnvÀnd din enhets lÄsskÀrm" Àr bÀttre Àn "autentisera med en invÄnare FIDO2 inloggningsuppgifter."
Misstag jag skulle undvika
Generera inte utmaningar pÄ klienten. Utmaningen skapas pÄ servern och mÄste endast verifieras en gÄng.
Lita inte bara pÄ legitimations-ID. Du mÄste verifiera signatur, utmaning, ursprung och Relying Party ID.
Ta inte bort fallbacks innan du har ett bra ÄterstÀllningsflöde. Lösenordslös behöver inte bli "om du tappar din telefon Àr du ute för alltid".
Behandla inte passkey som en ren frontend-knapp. Att dölja en knapp Àr inte sÀkerhet: den verkliga verifieringen Àr serversidan.
Passkey-först eller passkey-vÀnlig?
För en ny produkt kan du tÀnka passkey-först. För en befintlig app föredrar jag passkey-vÀnlig: lÀgg till passkey som en rekommenderad metod, mÀt framgÄng och problem och minska sedan lugnt lösenordsvikten.
Den ideala migrationen kÀnns inte. AnvÀndaren upptÀcker att det Àr lÀttare att logga in, inte att företaget har Àndrat sitt autentiseringsprotokoll.
Slutsats
passkey Àr intressanta eftersom de förbÀttrar sÀkerheten och UX samtidigt, vilket Àr sÀllsynt. De Àr inte ett trollspö: ÄterhÀmtning, kompatibilitet, stöd och utrullning ÄterstÄr att utformas vÀl.
Men den grundlÀggande förÀndringen Àr stark. Sluta be anvÀndarna att uppfinna och skydda hemligheter. Du lÄter enheten signera ett kryptografiskt bevis kopplat till din domÀn. Mindre mÀnskligt minne, mindre nÀtfiske, fÀrre lösenordsÄterstÀllningar. Jag skulle sÀga att de Àr vÀrda att ta pÄ allvar.