Crea un'esperienza di accesso che sfrutti le passkey e che tenga conto degli utenti che utilizzano le password.
Questa guida spiega come utilizzare la compilazione automatica dei moduli per consentire agli utenti di accedere con le passkey insieme alle password. L'utilizzo della compilazione automatica dei moduli crea un'esperienza di accesso unificata, semplificando la transizione dalle password al metodo di autenticazione con passkey più sicuro e facile da usare.
Scopri come implementare l'interfaccia utente condizionale di WebAuthn per supportare gli utenti di passkey e password con un attrito minimo nei moduli di accesso esistenti.
Perché utilizzare la compilazione automatica dei moduli per accedere con una passkey?
Le passkey consentono agli utenti di accedere ai siti web utilizzando l'impronta, il volto o il PIN del dispositivo.
Se tutti gli utenti avessero passkey, il flusso di autenticazione potrebbe essere un unico pulsante di accesso. Se tocca il pulsante, l'utente può verificare direttamente l'account con il blocco schermo e accedere.
Tuttavia, il passaggio dalle password alle passkey presenta delle sfide. Durante questo periodo, i siti web devono supportare sia gli utenti con password sia quelli con passkey. Chiedere agli utenti di ricordare quali siti utilizzano le passkey e di scegliere un metodo di accesso in anticipo crea un'esperienza utente negativa.
Le passkey sono anche una nuova tecnologia e spiegarle in modo chiaro può essere difficile. L'utilizzo della familiare interfaccia di compilazione automatica aiuta ad affrontare sia la sfida della transizione sia la necessità di familiarità per gli utenti.
Utilizzare l'interfaccia utente condizionale
Per supportare in modo efficace gli utenti di passkey e password, includi le passkey nei suggerimenti di riempimento automatico del modulo. Questo approccio utilizza l' interfaccia utente condizionale, una funzionalità dello standard WebAuthn.
Quando l'utente si concentra sul campo di immissione del nome utente, viene visualizzata una finestra di dialogo di compilazione automatica, che suggerisce le passkey memorizzate insieme alle password salvate. L'utente può selezionare una passkey o una password e procedere all'accesso utilizzando il blocco schermo del dispositivo se sceglie una passkey.
In questo modo, gli utenti possono accedere al tuo sito web con il modulo di accesso esistente, ma con il vantaggio di sicurezza aggiuntivo delle passkey se ne hanno una.
Come funziona l'autenticazione con passkey
Per autenticarti con una passkey, utilizza l'API WebAuthn.
I quattro componenti di un flusso di autenticazione con passkey sono:
- Backend: memorizza i dettagli dell'account utente, inclusa la chiave pubblica.
- Frontend: comunica con il browser e recupera i dati necessari dal backend.
- Browser: esegue il codice JavaScript e interagisce con l'API WebAuthn.
- Fornitore di passkey: crea e memorizza la passkey. In genere si tratta di un gestore delle password come Gestore delle password di Google o di un token di sicurezza.
La procedura di autenticazione con le passkey segue questo flusso:
- L'utente visita la pagina di accesso e il frontend richiede una verifica di autenticazione dal backend.
- Il backend genera e restituisce una richiesta WebAuthn associata all'account dell'utente.
- Il frontend chiama
navigator.credentials.get()con la sfida per avviare l'autenticazione utilizzando il browser. - Il browser, interagendo con il provider di passkey, chiede all'utente di selezionare una passkey (spesso utilizzando una finestra di dialogo di compilazione automatica attivata mettendo il cursore nel campo di accesso) e di verificare la propria identità utilizzando il blocco schermo o la biometria del dispositivo.
- Dopo la verifica riuscita dell'utente, il fornitore di passkey firma la sfida e il browser restituisce la credenziale della chiave pubblica risultante (inclusa la firma) al frontend.
- Il frontend invia questa credenziale al backend.
- Il backend verifica la firma della credenziale rispetto alla chiave pubblica memorizzata dell'utente. Se la verifica ha esito positivo, il backend esegue l'accesso dell'utente.
Autenticarsi con una passkey tramite la compilazione automatica dei moduli
Per avviare l'autenticazione con passkey utilizzando la compilazione automatica dei moduli, effettua una chiamata
WebAuthn get condizionale al caricamento della pagina di accesso. Questa chiamata a
navigator.credentials.get() include l'opzione mediation: 'conditional'.
Una richiesta condizionale all'API WebAuthn
navigator.credentials.get() non mostra immediatamente l'UI. ma rimane in stato di attesa finché l'utente non interagisce con il prompt di compilazione automatica del campo del nome utente. Se l'utente seleziona una passkey, il browser risolve la promessa in attesa con una credenziale per accedere, bypassando l'invio del modulo tradizionale. Se l'utente sceglie una password, la promessa non viene risolta
e continua il flusso di accesso con password standard.rm. È quindi responsabilità della pagina
accedere per conto dell'utente.
Annotare il campo di immissione del modulo
Per attivare il riempimento automatico delle passkey, aggiungi l'attributo autocomplete al campo
nome utente input del modulo. Includi sia username sia webauthn come
valori separati da spazi.
<input type="text" name="username" autocomplete="username webauthn" autofocus>
L'aggiunta di autofocus a questo campo attiva automaticamente la richiesta di compilazione automatica al caricamento della pagina, mostrando immediatamente le password e le passkey disponibili.
Rilevamento delle funzionalità
Prima di richiamare una chiamata API WebAuthn condizionale, controlla se:
- Il browser supporta WebAuthn con
PublicKeyCredential.
- Il browser supporta il rilevamento delle funzionalità con
PublicKeyCredential.getClientCapabilities().
- Il browser supporta l'interfaccia utente
condizionale di WebAuthn con
conditionalGet.
Il seguente snippet mostra come puoi verificare se il browser supporta queste funzionalità:
if (window.PublicKeyCredential && PublicKeyCredential.getClientCapabilities) {
const capabilities = await PublicKeyCredential.getClientCapabilities();
// Check if conditional mediation is available.
if (capabilities.conditionalGet === true) {
// The browser supports conditional mediation.
}
}
Recuperare informazioni dal backend
Il backend deve fornire diverse opzioni al frontend per avviare la chiamata
navigator.credentials.get(). Queste opzioni vengono in genere recuperate come
oggetto JSON da un endpoint sul tuo server.
Le proprietà chiave nell'oggetto delle opzioni includono:
challenge: Una sfida generata dal server in un ArrayBuffer (in genere codificata in Base64URL per il trasporto JSON). Questo è essenziale per prevenire gli attacchi di replay. Il server deve generare una nuova verifica per ogni tentativo di accesso e invalidarla dopo un breve periodo di tempo o se un tentativo non riesce.allowCredentials: un array di descrittori delle credenziali. Passa un array vuoto. In questo modo il browser elenca tutte le credenziali per ilrpIdspecificato.userVerification: Specifica la tua preferenza per la verifica dell'utente, ad esempio richiedendo un blocco schermo del dispositivo. Il valore predefinito e consigliato è"preferred". I valori possibili sono:"required": La verifica dell'utente deve essere eseguita dall'autenticatore (ad esempio PIN o dati biometrici). L'operazione non va a buon fine se non è possibile eseguire la verifica."preferred": L'autenticatore tenta la verifica dell'utente, ma l'operazione può riuscire senza."discouraged": se possibile, l'autenticatore deve evitare la verifica dell'utente.
rpId: l'ID della relying party, in genere il dominio del tuo sito web (ad esempioexample.com). Questo valore deve corrispondere esattamente arp.idutilizzato durante la creazione della credenziale passkey.
Il server deve creare questo oggetto di opzioni. I valori ArrayBuffer (come
challenge) devono essere codificati in Base64URL per il trasporto JSON. Nel frontend,
dopo l'analisi del JSON, utilizza
PublicKeyCredential.parseRequestOptionsFromJSON()
per convertire l'oggetto (inclusa la decodifica delle stringhe Base64URL) nel formato
previsto da navigator.credentials.get().
Il seguente snippet di codice mostra come recuperare e decodificare le informazioni necessarie per l'autenticazione con una passkey.
// Fetch an encoded PubicKeyCredentialRequestOptions from the server.
const _options = await fetch('/webauthn/signinRequest');
// Deserialize and decode the PublicKeyCredentialRequestOptions.
const decoded_options = JSON.parse(_options);
const options = PublicKeyCredential.parseRequestOptionsFromJSON(decoded_options);
...
Chiama l'API WebAuthn con il flag conditional per autenticare l'utente
Una volta preparato l'oggetto publicKeyCredentialRequestOptions (denominato
options nel codice di esempio riportato di seguito), chiama
navigator.credentials.get() per avviare l'autenticazione
con passkey condizionale.
// To abort a WebAuthn call, instantiate an AbortController.
const abortController = new AbortController();
// Invoke WebAuthn to authenticate with a passkey.
const credential = await navigator.credentials.get({
publicKey: options,
signal: abortController.signal,
// Specify 'conditional' to activate conditional UI
mediation: 'conditional'
});
Parametri chiave per questa chiamata:
publicKey: deve essere l'oggettopublicKeyCredentialRequestOptions(denominatooptionsnell'esempio) recuperato dal server e elaborato nel passaggio precedente.signal: il passaggio di un segnale diAbortController(ad esempioabortController.signal) consente di annullare a livello di programmazione la richiesta diget(). Questa operazione è utile quando vuoi richiamare un'altra chiamata WebAuthn.mediation: 'conditional': questo è il flag cruciale che rende condizionale la chiamata WebAuthn. Indica al browser di attendere l'interazione dell'utente con una richiesta di compilazione automatica anziché mostrare immediatamente una finestra di dialogo modale.
Invia le credenziali della chiave pubblica restituite al server RP
Se l'utente seleziona una passkey e verifica la propria identità (ad esempio, utilizzando il blocco schermo del dispositivo), la promessa navigator.credentials.get() viene risolta. Viene restituito
un oggetto PublicKeyCredential
al tuo frontend.
La promessa può essere rifiutata per diversi motivi. Devi gestire questi errori
nel tuo codice controllando la proprietà name dell'oggetto Error:
NotAllowedError: L'utente ha annullato l'operazione o non è stata selezionata alcuna passkey.AbortError: l'operazione è stata interrotta, probabilmente dal tuo codice utilizzando unAbortController.- Altre eccezioni: si è verificato un errore imprevisto. Il browser in genere mostra all'utente una finestra di dialogo di errore.
L'oggetto PublicKeyCredential contiene diverse proprietà. Le proprietà chiave
pertinenti per l'autenticazione includono:
id: L'ID codificato in base64url della credenziale passkey autenticata.rawId: Una versione ArrayBuffer dell'ID credenziale.response.clientDataJSON: Un ArrayBuffer di dati client. Questo campo contiene informazioni come la sfida e l'origine che il server deve verificare.response.authenticatorData: Un ArrayBuffer di dati dell'autenticatore. Questo campo include informazioni come l'ID RP.response.signature: Un ArrayBuffer contenente la firma. Questo valore è il fulcro della credenziale e il tuo server deve verificare questa firma utilizzando la chiave pubblica memorizzata per la credenziale .response.userHandle: Un ArrayBuffer che contiene l'ID utente fornito durante la registrazione della passkey.authenticatorAttachment: Indica se l'autenticatore fa parte del dispositivo client (platform) o è esterno (cross-platform). Un allegatocross-platformpuò verificarsi se l'utente ha eseguito l'accesso con un telefono. In questi casi, valuta la possibilità di invitarli a creare una passkey sul dispositivo attuale per comodità futura.type: questo campo è sempre impostato su"public-key".
Per inviare questo oggetto PublicKeyCredential al tuo backend, chiama prima il metodo
.toJSON(). Questo metodo crea una versione serializzabile in JSON della credenziale, che gestisce correttamente la conversione delle proprietà ArrayBuffer (come rawId, clientDataJSON, authenticatorData, signature e userHandle) in stringhe codificate in Base64URL. Quindi, utilizza JSON.stringify() per convertire questo oggetto in una stringa e inviarlo nel corpo della richiesta al server.
...
// Encode and serialize the PublicKeyCredential.
const _result = credential.toJSON();
const result = JSON.stringify(_result);
// Encode and send the credential to the server for verification.
const response = await fetch('/webauthn/signinResponse', {
method: 'post',
credentials: 'same-origin',
body: result
});
Verificare la firma
Quando il server di backend riceve la credenziale di chiave pubblica, deve verificarne l'autenticità. Ciò comporta:
- Analisi dei dati delle credenziali.
- Ricerca della chiave pubblica memorizzata associata a
iddella credenziale. - Verifica del
signaturericevuto rispetto alla chiave pubblica archiviata. - Convalida di altri dati, come la sfida e l'origine.
Ti consigliamo di utilizzare una libreria FIDO/WebAuthn lato server per gestire queste operazioni crittografiche in modo sicuro. Puoi trovare librerie open source nel repository GitHub awesome-webauthn.
Se la firma e tutte le altre asserzioni sono valide, il server può consentire l'accesso all'utente. Per i passaggi dettagliati di convalida lato server, consulta Autenticazione con passkey lato server.
Segnala se le credenziali corrispondenti non vengono trovate nel backend
Se il server di backend non riesce a trovare una credenziale con un ID corrispondente durante l'accesso, l'utente potrebbe aver eliminato in precedenza questa passkey dal server ma non dal provider di passkey. Questa mancata corrispondenza può portare a un'esperienza utente confusa se il fornitore di passkey continua a suggerire una passkey che non funziona più con il tuo sito. Per migliorare la situazione, devi segnalare al fornitore della passkey di rimuovere la passkey orfana.
Puoi utilizzare il metodo PublicKeyCredential.signalUnknownCredential(), parte dell'API Webauthn Signal, per comunicare al fornitore di passkey che le credenziali specificate sono state rimosse o non esistono. Chiama questo metodo statico sul lato client se il server
indica (ad esempio, con un codice di stato HTTP specifico come 404) che un
ID credenziale presentato è sconosciuto. Fornisci l'ID della parte soggetta a limitazioni e l'ID credenziale sconosciuto a questo metodo. Il fornitore di passkey, se supporta l'indicatore, deve
rimuovere la passkey.
// Detect authentication failure due to lack of the credential
if (response.status === 404) {
// Feature detection
if (PublicKeyCredential.signalUnknownCredential) {
await PublicKeyCredential.signalUnknownCredential({
rpId: "example.com",
credentialId: "vI0qOggiE3OT01ZRWBYz5l4MEgU0c7PmAA" // base64url encoded credential ID
});
} else {
// Encourage the user to delete the passkey from the password manager nevertheless.
...
}
}
Dopo l'autenticazione
A seconda della modalità di accesso dell'utente, suggeriamo di seguire flussi diversi.
Se l'utente ha eseguito l'accesso senza una passkey
Se l'utente ha eseguito l'accesso al tuo sito web senza una passkey, è possibile che non ne abbia registrata una per quell'account o sul dispositivo attuale. Questo è un momento opportuno per incoraggiare la creazione di passkey. Considera i seguenti approcci:
- Esegui l'upgrade delle password alle passkey: utilizza conditional create, una funzionalità di WebAuthn che consente al browser di creare automaticamente una passkey per l'utente dopo l'accesso riuscito con password. Ciò può migliorare notevolmente l'adozione delle passkey semplificando il processo di creazione. Scopri come funziona e come implementarla in Aiutare gli utenti ad adottare le passkey in modo più semplice
- Richiedi manualmente la creazione della passkey: incoraggia gli utenti a creare una passkey. Questo può essere efficace dopo che un utente completa una procedura di accesso più complessa, come l'autenticazione a più fattori (MFA). Tuttavia, evita prompt eccessivi, che possono essere intrusivi per l'esperienza utente."
Per scoprire come incoraggiare gli utenti a creare una passkey e conoscere altre buone pratiche, consulta gli esempi riportati nella sezione Comunicare le passkey agli utenti.
Se l'utente ha eseguito l'accesso con una passkey
Dopo che un utente ha eseguito l'accesso con una passkey, hai diverse opportunità per migliorare ulteriormente la sua esperienza e mantenere la coerenza dell'account.
Incoraggiare la creazione di una nuova passkey dopo un'autenticazione cross-device
Se un utente accede con una passkey utilizzando un meccanismo cross-device (ad esempio, scansionando un codice QR con il proprio smartphone), la passkey utilizzata potrebbe non essere memorizzata localmente sul dispositivo su cui sta accedendo. Questo si verifica se:
- Hanno una passkey, ma su un fornitore di passkey che non supporta il sistema operativo o il browser di accesso.
- Non hanno più accesso al fornitore di passkey sul dispositivo di accesso, ma una passkey è ancora disponibile su un altro.
In questa situazione, valuta la possibilità di chiedere all'utente di creare una nuova passkey sul
dispositivo attuale. In questo modo, in futuro non dovranno ripetere la procedura di accesso cross-device. Per determinare se l'utente ha eseguito l'accesso utilizzando una passkey cross-device, controlla la proprietà authenticatorAttachment della credenziale. Se il suo valore è "cross-platform", indica un'autenticazione
cross-device. In questo caso, spiega la comodità di creare una nuova passkey e
guida l'utente nella procedura di creazione.
Sincronizzare i dettagli della passkey con il fornitore utilizzando gli indicatori
Per garantire coerenza e una migliore esperienza utente, la tua Relying Party (RP) può utilizzare l'API WebAuthn Signals per comunicare aggiornamenti su credenziali e informazioni utente al fornitore di passkey.
Ad esempio, per mantenere accurato l'elenco delle passkey di un utente del provider di passkey, mantieni sincronizzate le credenziali nel backend. Puoi segnalare che una passkey non esiste più in modo che i fornitori di passkey possano rimuovere quelle non necessarie.
Analogamente, puoi segnalare se un utente aggiorna il proprio nome utente o nome visualizzato sul tuo servizio, per contribuire a mantenere aggiornate le informazioni dell'utente visualizzate dal fornitore di passkey (ad esempio, nelle finestre di dialogo di selezione dell'account).
Per scoprire di più sulle best practice per mantenere le passkey coerenti, consulta Mantenere le passkey coerenti con le credenziali sul server con l'API Signal.
Non richiedere un secondo fattore
Le passkey offrono una protezione integrata e robusta contro minacce comuni come il phishing. Pertanto, un secondo fattore di autenticazione non aggiunge un valore di sicurezza significativo. Al contrario, crea un passaggio non necessario per gli utenti durante l'accesso.
Elenco di controllo
- Consenti agli utenti di accedere con una passkey tramite la compilazione automatica dei moduli.
- Segnala quando le credenziali corrispondenti di una passkey non vengono trovate nel backend.
- Chiedi agli utenti di creare manualmente una passkey se non ne hanno ancora creata una dopo l'accesso.
- Crea automaticamente una passkey (creazione condizionale) dopo che l'utente ha eseguito l'accesso con una password (e un secondo fattore).
- Richiedi la creazione di una passkey locale se l'utente ha eseguito l'accesso con una passkey cross-device.
- Segnala al provider l'elenco delle passkey disponibili e i dettagli utente aggiornati (nome utente, nome visualizzato) dopo l'accesso o quando si verificano modifiche.
Risorse
- Autenticazione con passkey lato server
- Creare una passkey per gli accessi senza password
- Aiutare gli utenti a gestire le passkey in modo efficace
- Passkey
- Documento Apple: Authenticating a User Through a Web Service (Autenticazione di un utente tramite un servizio web)
- Documento Google: accesso senza password con le passkey