NAME
passkeys-webauthn-passwordless-authentication — Passkey och WebAuthn: logga in utan lösenord, utan magi
SYNOPSIS
cat passkeys-webauthn-passwordless-authentication.md
DESCRIPTION
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.
Källor
METADATA
- date: 2026-05-01
- reading: 4 min
- author: Filippo Spinella
- tags: Security, WebAuthn, Authentication, Web Development