spinny:~/writing $ vim passkeys-webauthn-passwordless-authentication.md
1~2Parolele sunt unul dintre acele lucruri pe care le-am normalizat doar pentru că am trăit cu ele de ani de zile. Utilizatorii le uită, le refolosesc, le scriu acolo unde nu ar trebui. Echipele trebuie să gestioneze resetările, politicile, hashurile, scurgerile, phishingul și asistența.3~4passkey nu fac autentificarea perfectă, dar înlătură o problemă uriașă: serverul nu mai trebuie să păstreze un secret partajat cu utilizatorul.5~6## Ce se întâmplă cu adevărat7~8Un passkey este o acreditare bazată pe WebAuthn. Când utilizatorul îl creează, dispozitivul generează o pereche de chei:9~10- o cheie privată, care rămâne pe dispozitiv sau în managerul de parole;11- o cheie publică, pe care serverul o poate salva.12~13Când vă autentificați, serverul nu vă întreabă „spuneți-mi parola”. Trimite o provocare aleatorie. Dispozitivul îl semnează cu cheia privată. Serverul verifică semnătura cu cheia publică.14~15Aceasta este partea frumoasă: dacă baza de date este furată, nu există parole de spart. Și dacă un utilizator ajunge pe un domeniu fals, passkey nu este valabil pentru acel domeniu. Nu este doar comoditate, este o protecție concretă împotriva phishingului.16~17## Browserul acționează ca o punte18~19În browser, cele două API principale sunt:20~21- `navigator.credentials.create()` pentru a crea un passkey;22- `navigator.credentials.get()` pentru a-l folosi în timpul conectării.23~24Dar logica importantă este pe server. Serverul trebuie să genereze provocarea, să o salveze temporar, să verifice răspunsul, să verifice sursa și Relying Party ID, apoi să creeze sesiunea.25~26Partea client ar trebui să fie aproape plictisitoare: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~42Dacă implementați manual criptarea WebAuthn, opriți-vă. Utilizați o bibliotecă robustă pe partea de server. Erorile de aici nu sunt „bucuri drăguțe”, ci găuri de autentificare.43~44## Ce să salvezi în baza de date45~46Nu este nevoie să salvezi jumătate din lume. De obicei suficient:47~48- ID-ul acreditării;49- cheie publică;50- utilizator conectat;51- orice contor de verificare sau metadate;52- transporturi, dacă sunt utile pentru UX;53- numele ales de utilizator;54- data creării și ultima utilizare.55~56Un tabel minim ar putea arăta astfel: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~70Apoi aș adăuga jurnale de audit și notificări: dacă cineva creează un nou passkey pe contul meu, vreau să știu despre asta.71~72## UX contează mai mult decât demonstrația73~74Demo-ul unui passkey este întotdeauna frumos: dați clic, Face ID, sunteți. Produsul propriu-zis este mai complicat.75~76Cineva își schimbă telefonul. Cineva folosește un computer al companiei blocat. Unii oameni nu înțeleg de ce browserul sugerează un passkey. Cineva pierde accesul la dispozitivul său.77~78Acesta este motivul pentru care nu aș începe cu „de azi nu mai sunt parole pentru toată lumea”. as incepe asa:79~801. passkey opțional pentru utilizatorii interni;812. sugestie de a crea unul după o conectare cu succes;823. pagina de cont pentru a redenumi și a elimina passkey;834. alternativă clară;845. lansare treptată în login principal.85~86Textul din interfață ar trebui să fie simplu. „Utilizați ecranul de blocare al dispozitivului” este mai bine decât „autentificați-vă cu o autentificare rezidentă FIDO2”.87~88## Greșeli pe care le-aș evita89~90Nu generați provocări clientului. Provocarea este creată pe server și trebuie verificată o singură dată.91~92Nu aveți încredere doar în ID-ul acreditării. Trebuie să verificați semnătura, provocarea, originea și Relying Party ID.93~94Nu ștergeți fallback-urile înainte de a avea un flux bun de recuperare. Fără parolă nu trebuie să devină „dacă îți pierzi telefonul, ești afară pentru totdeauna”.95~96Nu tratați passkey ca pe un buton pur frontal. Ascunderea unui buton nu este securitate: verificarea reală este pe partea serverului.97~98## Passkey-primul sau passkey prietenos?99~100Pentru un produs nou te poți gândi la passkey-întâi. Pentru o aplicație existentă prefer passkey: adăugați passkey ca metodă recomandată, măsurați succesul și problemele, apoi reduceți cu calm greutatea parolei.101~102Migrația ideală nu se simte. Utilizatorul descoperă că autentificarea este mai ușoară, nu că compania și-a schimbat protocolul de autentificare.103~104## Concluzie105~106passkey sunt interesante pentru că îmbunătățesc securitatea și UX în același timp, ceea ce este rar. Nu sunt o baghetă magică: recuperarea, compatibilitatea, suportul și lansarea rămân bine concepute.107~108Dar schimbarea de bază este puternică. Nu le mai cere utilizatorilor să inventeze și să protejeze secretele. Permiteți dispozitivului să semneze o dovadă criptografică legată de domeniul dvs. Mai puțină memorie umană, mai puțin phishing, mai puține resetări de parole. Aș spune că merită luate în serios.109~110## Surse111~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