Accedere con una passkey tramite la compilazione automatica dei moduli

Crea un'esperienza di accesso che utilizzi le passkey pur continuando a supportare gli utenti con password esistenti.

Eiji Kitamura
Eiji Kitamura

Le passkey sostituiscono le password e rendono gli account utente sul Web più sicuri, semplici e facili da usare. Tuttavia, il passaggio dall'autenticazione basata su password a quella basata su passkey può complicare l'esperienza utente. L'utilizzo della compilazione automatica dei moduli per suggerire le passkey può contribuire a creare un'esperienza unificata.

Perché usare la compilazione automatica dei moduli per accedere con una passkey?

Con una passkey, un utente può accedere a un sito web utilizzando l'impronta, il volto o il PIN del dispositivo.

Idealmente, non ci sarebbero utenti con password e il flusso di autenticazione potrebbe essere semplice quanto un singolo pulsante di accesso. Quando l'utente tocca il pulsante, viene visualizzata una finestra di dialogo del selettore di account e l'utente può scegliere un account, sbloccare la schermata di verifica e accedere.

Tuttavia, la transizione dall'autenticazione basata su password all'autenticazione basata su passkey può essere complicata. Man mano che gli utenti passano alle passkey, ci saranno ancora coloro che utilizzano password e siti web dovranno soddisfare entrambi i tipi di utenti. Gli utenti non dovrebbero ricordarsi su quali siti sono passati alle passkey, quindi chiedere agli utenti di selezionare in anticipo il metodo da utilizzare non sarebbe soddisfacente.

Le passkey sono una nuova tecnologia. Spiegarli e assicurarsi che gli utenti si sentano a loro agio a utilizzarli possono rappresentare una sfida per i siti web. Possiamo fare affidamento su esperienze utente familiari per la compilazione automatica delle password e risolvere entrambi i problemi.

UI condizionale

Per creare un'esperienza utente efficiente sia per gli utenti con passkey che per le password, puoi includere le passkey nei suggerimenti di compilazione automatica. Questa è chiamata UI condizionale e fa parte dello standard WebAuthn.

Non appena l'utente tocca il campo di immissione del nome utente, viene visualizzata una finestra di dialogo con suggerimenti di compilazione automatica che evidenzia le passkey memorizzate e i suggerimenti per la compilazione automatica delle password. L'utente può quindi scegliere un account e utilizzare il blocco schermo del dispositivo per accedere.

In questo modo, gli utenti possono accedere al tuo sito web con il modulo esistente come se non fosse cambiato nulla, ma con il vantaggio aggiuntivo per la sicurezza delle passkey, se ne hanno una.

Come funziona

Per autenticarti con una passkey, utilizza l'API WebAuthn.

I quattro componenti di un flusso di autenticazione delle passkey sono: l'utente:

  • Backend: il server di backend che contiene il database degli account in cui è archiviata la chiave pubblica e altri metadati relativi alla passkey.
  • Frontend: il frontend che comunica con il browser e invia richieste di recupero al backend.
  • Browser: il browser dell'utente su cui è in esecuzione JavaScript.
  • Authenticator: l'autenticatore dell'utente che crea e memorizza la passkey. Potrebbe trovarsi sullo stesso dispositivo del browser (ad es. quando usi Windows Hello) o su un altro dispositivo, ad esempio un telefono.
Diagramma dell'autenticazione con passkey
  1. Non appena un utente arriva sul frontend, richiede al backend una richiesta di autenticazione con una passkey e chiama navigator.credentials.get() per avviare l'autenticazione con una passkey. Viene restituito un Promise.
  2. Quando l'utente posiziona il cursore nel campo di accesso, nel browser viene visualizzata una finestra di dialogo di compilazione automatica delle password che includono le passkey. Se l'utente seleziona una passkey, viene visualizzata una finestra di dialogo di autenticazione.
  3. Dopo che l'utente ha verificato la propria identità utilizzando il blocco schermo del dispositivo, la promessa viene risolta e viene restituita una credenziale di chiave pubblica al frontend.
  4. Il frontend invia la credenziale della chiave pubblica al backend. Il backend verifica la firma in base alla chiave pubblica dell'account corrispondente nel database. Se l'operazione va a buon fine, l'utente esegue l'accesso.

Prerequisiti

La UI condizionale WebAuthn è supportata pubblicamente in Safari su iOS 16, iPadOS 16 e macOS Ventura. È disponibile anche su Chrome per Android, macOS e Windows 11 22H2.

Autenticazione con una passkey tramite la compilazione automatica dei moduli

Quando un utente vuole accedere, puoi effettuare una chiamata condizionale get a WebAuthn per indicare che le passkey potrebbero essere incluse nei suggerimenti di compilazione automatica. Una chiamata condizionale all'API navigator.credentials.get() di WebAuthn non mostra l'interfaccia utente e rimane in attesa finché l'utente non sceglie un account con cui accedere dai suggerimenti di compilazione automatica. Se l'utente sceglie una passkey, il browser risolverà la promessa con una credenziale anziché compilare il modulo di accesso. La pagina ha quindi la responsabilità di eseguire l'accesso dell'utente.

Campo di immissione del modulo per l'annotazione

Se necessario, aggiungi un attributo autocomplete al campo del nome utente input. Aggiungi username e webauthn come token per consentire al dispositivo di suggerire le passkey.

<input type="text" name="username" autocomplete="username webauthn" ...>

Rilevamento funzionalità

Prima di richiamare una chiamata API WebAuthn condizionale, controlla se:

  • Il browser supporta WebAuthn.
  • Il browser supporta l'interfaccia utente condizionale WebAuthn.
// Availability of `window.PublicKeyCredential` means WebAuthn is usable.  
if (window.PublicKeyCredential &&  
    PublicKeyCredential.​​isConditionalMediationAvailable) {  
  // Check if conditional mediation is available.  
  const isCMA = await PublicKeyCredential.​​isConditionalMediationAvailable();  
  if (isCMA) {  
    // Call WebAuthn authentication  
  }  
}  

Recupero di una richiesta di verifica dal server RP

Recupera dal server RP un test richiesto per chiamare navigator.credentials.get():

  • challenge: Un test generato dal server in un ArrayBuffer. Questa operazione è necessaria per evitare attacchi replay. Assicurati di generare una nuova verifica a ogni tentativo di accesso e ignorala dopo un determinato periodo di tempo o se un tentativo di accesso non riesce a essere convalidato. Consideralo un token CSRF.
  • allowCredentials: un array di credenziali accettabili per questa autenticazione. Passa un array vuoto per consentire all'utente di selezionare una passkey disponibile da un elenco mostrato dal browser.
  • userVerification: Indica se la verifica dell'utente mediante il blocco schermo del dispositivo è "required", "preferred" o "discouraged". Il valore predefinito è "preferred", il che significa che l'autenticatore potrebbe saltare la verifica dell'utente. Impostalo su "preferred" oppure ometti la proprietà.

Chiama l'API WebAuthn con il flag conditional per autenticare l'utente

Chiama il numero navigator.credentials.get() per iniziare ad attendere l'autenticazione dell'utente.

// To abort a WebAuthn call, instantiate an `AbortController`.
const abortController = new AbortController();

const publicKeyCredentialRequestOptions = {
  // Server generated challenge
  challenge: ****,
  // The same RP ID as used during registration
  rpId: 'example.com',
};

const credential = await navigator.credentials.get({
  publicKey: publicKeyCredentialRequestOptions,
  signal: abortController.signal,
  // Specify 'conditional' to activate conditional UI
  mediation: 'conditional'
});
  • rpId: Un ID RP è un dominio e un sito web può specificare il proprio dominio o un suffisso registrabile. Questo valore deve corrispondere al valore rp.id utilizzato al momento della creazione della passkey.

Ricordati di specificare mediation: 'conditional' per rendere condizionale la richiesta.

Invia la credenziale di chiave pubblica restituita al server RP

Dopo che l'utente ha selezionato un account e acconsentito utilizzando il blocco schermo del dispositivo, la promessa viene risolta restituendo un oggetto PublicKeyCredential al frontend RP.

Una promessa può essere rifiutata per diversi motivi. Devi gestire gli errori di conseguenza, a seconda della proprietà name dell'oggetto Error:

  • NotAllowedError: l'utente ha annullato l'operazione.
  • Altre eccezioni: si è verificato un problema imprevisto. Il browser mostra all'utente una finestra di dialogo di errore.

L'oggetto credenziali di chiave pubblica contiene le seguenti proprietà:

  • id: l'ID codificato in base64url della credenziale della passkey autenticata.
  • rawId: una versione Arraybuffer dell'ID credenziale.
  • response.clientDataJSON: un Arraybuffer di dati client. Questo campo contiene informazioni come il challenge e l'origine che il server RP dovrà verificare.
  • response.authenticatorData: un Arraybuffer di dati dell'autenticatore. Questo campo contiene informazioni come l'ID RP.
  • response.signature: un ArrayBuffer della firma. Questo valore è il nucleo della credenziale e deve essere verificato sul server.
  • response.userHandle: un Arraybuffer contenente l'ID utente impostato al momento della creazione. Questo valore può essere utilizzato, al posto dell'ID credenziale, se il server deve scegliere i valori ID che utilizza o se il backend vuole evitare di creare un indice sugli ID credenziali.
  • authenticatorAttachment: restituisce platform quando la credenziale proviene dal dispositivo locale. In caso contrario cross-platform, in particolare quando l'utente ha utilizzato un telefono per accedere. Se l'utente ha dovuto utilizzare un telefono per accedere, puoi chiedergli di creare una passkey sul dispositivo locale.
  • type: questo campo è sempre impostato su "public-key".

Se utilizzi una libreria per gestire l'oggetto credenziali di chiave pubblica sul server RP, ti consigliamo di inviare l'intero oggetto al server dopo averlo codificato parzialmente con base64url.

Verificare la firma

Quando ricevi la credenziale di chiave pubblica sul server, passala alla libreria FIDO per elaborare l'oggetto.

Cerca l'ID credenziale corrispondente con la proprietà id (se devi determinare l'account utente, utilizza la proprietà userHandle che è il user.id specificato durante la creazione della credenziale). Vedi se le credenziali signature possono essere verificate con la chiave pubblica archiviata. A questo scopo, ti consigliamo di utilizzare una libreria lato server o una soluzione anziché scrivere il tuo codice. Troverai le librerie open source nel repository GitHub di impression-webauth.

Dopo aver verificato la credenziale con una chiave pubblica corrispondente, fai accedere l'utente.

Risorse