Le credenziali FIDO, come le passkey, mirano a sostituire le password, ma la maggior parte di queste permettono anche all'utente di evitare di digitare un nome utente. In questo modo, gli utenti possono eseguire l'autenticazione selezionando un account da un elenco di passkey che hanno per il sito web attuale.
Le versioni precedenti dei token di sicurezza sono state progettate come metodi di autenticazione in due passaggi e richiedevano gli ID delle potenziali credenziali, quindi la digitazione di un nome utente. Le credenziali che un token di sicurezza può trovare senza conoscere i relativi ID sono chiamate credenziali rilevabili. La maggior parte delle credenziali FIDO create oggi sono credenziali rilevabili, in particolare le passkey memorizzate in un gestore delle password o su un moderno token di sicurezza.
Per assicurarti che le credenziali vengano create come passkey (credenziali rilevabili), specifica residentKey
e requireResidentKey
al momento della creazione.
Le parti attendibili (RP) possono utilizzare le credenziali rilevabili omettendo
allowCredentials
durante l'autenticazione con passkey. In questi casi, il browser o il sistema mostra all'utente un elenco di passkey disponibili, identificate dalla proprietà user.name
impostata al momento della creazione. Se l'utente ne seleziona uno, il valore user.id
verrà incluso nella firma risultante. Il server può quindi utilizzare questo valore o
l'ID credenziale restituito per cercare l'account anziché un nome utente digitato.
Le UI del selettore di account, come quelle discusse in precedenza, non mostrano mai le credenziali non rilevabili.
requireResidentKey
e residentKey
Per creare una passkey, specifica authenticatorSelection.residentKey
e authenticatorSelection.requireResidentKey
su navigator.credentials.create()
con i valori indicati di seguito.
async function register () {
// ...
const publicKeyCredentialCreationOptions = {
// ...
authenticatorSelection: {
authenticatorAttachment: 'platform',
residentKey: 'required',
requireResidentKey: true,
}
};
const credential = await navigator.credentials.create({
publicKey: publicKeyCredentialCreationOptions
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
residentKey
:
'required'
: è necessario creare una credenziale rilevabile. Se non può essere creato, viene restituitoNotSupportedError
.'preferred'
: l'RP preferisce creare una credenziale rilevabile, ma accetta una credenziale non rilevabile.'discouraged'
: l'RP preferisce creare una credenziale non rilevabile, ma ne accetta una rilevabile.
requireResidentKey
:
- Questa proprietà viene mantenuta per la compatibilità con le versioni precedenti di WebAuthn livello 1, una versione precedente della specifica. Imposta questo valore su
true
seresidentKey
è'required'
, altrimenti impostalo sufalse
.
allowCredentials
Gli RP possono utilizzare allowCredentials
su navigator.credentials.get()
per controllare l'esperienza di autenticazione con passkey. In genere esistono tre tipi di esperienze di autenticazione con passkey:
- Mostrare un selettore di account modale
- Mostrare la compilazione automatica di un modulo per le passkey
- Rieseguire l'autenticazione
Mostra un selettore di account modale
Con le credenziali rilevabili, i RP possono mostrare un selettore di account modale per consentire all'utente di selezionare un account con cui accedere, seguito dalla verifica dell'utente. È adatto al flusso di autenticazione con passkey avviato premendo un pulsante dedicato all'autenticazione con passkey.
Per ottenere questa esperienza utente, ometti o passa un array vuoto al parametro allowCredentials
in navigator.credentials.get()
.
async function authenticate() {
// ...
const publicKeyCredentialRequestOptions = {
// Server generated challenge:
challenge: ****,
// The same RP ID as used during registration:
rpId: 'example.com',
// You can omit `allowCredentials` as well:
allowCredentials: []
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
Mostrare la compilazione automatica di un modulo per le passkey
Il selettore di account modale descritto sopra funziona bene se la maggior parte degli utenti utilizza le passkey e le ha disponibili sul dispositivo locale. Per un utente che non ha passkey locali, viene comunque visualizzata la finestra di dialogo modale che gli consentirà di presentare una passkey da un altro dispositivo. Durante la transizione degli utenti alle passkey, ti consigliamo di evitare questa interfaccia utente per gli utenti che non ne hanno configurata una.
Invece, la selezione di una passkey potrebbe essere inserita nelle richieste di compilazione automatica dei campi in un modulo di accesso tradizionale, insieme ai nomi utente e alle password salvati. In questo modo, un utente con passkey può "compilare" il modulo di accesso selezionando la propria passkey, gli utenti con coppie di nome utente/password salvate possono selezionarle e gli utenti che non hanno né l'una né l'altra possono comunque digitare il nome utente e la password.
Questa esperienza utente è ideale quando l'RP è in fase di migrazione con un utilizzo misto di password e passkey.
Per ottenere questa esperienza utente, oltre a passare un array vuoto alla proprietà allowCredentials
o a omettere il parametro, specifica mediation: 'conditional'
su navigator.credentials.get()
e annota un campo di immissione username
HTML con autocomplete="username webauthn"
o un campo di immissione password
con autocomplete="password webauthn"
.
La chiamata a navigator.credentials.get()
non comporta la visualizzazione di alcuna UI, ma se l'utente attiva il campo di immissione annotato, tutte le passkey disponibili verranno incluse nelle opzioni di compilazione automatica. Se l'utente ne seleziona uno, verrà eseguita la normale verifica di sblocco del dispositivo e solo a quel punto la promessa restituita da .get()
verrà risolta con un risultato. Se l'utente non seleziona una passkey, la promessa non viene mai risolta.
async function authenticate() {
// ...
const publicKeyCredentialRequestOptions = {
// Server generated challenge:
challenge: ****,
// The same RP ID as used during registration:
rpId: 'example.com',
// You can omit `allowCredentials` as well:
allowCredentials: []
};
const cred = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal,
// Specify 'conditional' to activate conditional UI
mediation: 'conditional'
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
<input type="text" name="username" autocomplete="username webauthn" ...>
Per scoprire come creare questa esperienza utente, consulta l'articolo Accedere con una passkey tramite la compilazione automatica dei moduli e il codelab Implementare le passkey con la compilazione automatica dei moduli in un'app web.
Riautenticazione
In alcuni casi, ad esempio quando utilizzi le passkey per la riautenticazione, l'identificatore dell'utente è già noto. In questo caso, vorremmo utilizzare una passkey senza che il browser o il sistema operativo mostri alcuna forma di selettore di account. Questo risultato può essere ottenuto passando un elenco di ID credenziali nel parametro allowCredentials
.
In questo caso, se una delle credenziali denominate è disponibile localmente, all'utente viene chiesto immediatamente di sbloccare il dispositivo. In caso contrario, all'utente viene chiesto di presentare un altro dispositivo (uno smartphone o un token di sicurezza) che contenga una credenziale valida.
Per ottenere questa esperienza utente, fornisci un elenco di ID credenziale per l'utente che accede. L'RP dovrebbe essere in grado di eseguire query perché l'utente è già noto. Fornisci gli ID credenziali come oggetti PublicKeyCredentialDescriptor
nella proprietà allowCredentials
in navigator.credentials.get()
.
async function authenticate() {
// ...
const publicKeyCredentialRequestOptions = {
// Server generated challenge:
challenge: ****,
// The same RP ID as used during registration:
rpId: 'example.com',
// Provide a list of PublicKeyCredentialDescriptors:
allowCredentials: [{
id: ****,
type: 'public-key',
transports: [
'internal',
'hybrid'
]
}, {
id: ****,
type: 'public-key',
transports: [
'internal',
'hybrid'
]
}, ...]
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
Un oggetto PublicKeyCredentialDescriptor
è costituito da:
id
: un ID della credenziale della chiave pubblica ottenuta dall'RP durante la registrazione della passkey.type
: in genere questo campo è'public-key'
.transports
: un suggerimento sui trasporti supportati dal dispositivo che contiene questa credenziale, utilizzato dai browser per ottimizzare l'interfaccia utente che chiede all'utente di presentare un dispositivo esterno. Questo elenco, se fornito, deve contenere il risultato della chiamata agetTransports()
durante la registrazione di ogni credenziale.
Riepilogo
Le credenziali rilevabili rendono l'esperienza di accesso con passkey molto più facile da usare, consentendo agli utenti di saltare l'inserimento di un nome utente. Con la combinazione di residentKey
, requireResidentKey
e allowCredentials
, i RP possono offrire esperienze di accesso che:
- Mostra un selettore di account modale.
- Mostra la compilazione automatica di un modulo per le passkey.
- Riautenticazione.
Usa le credenziali rilevabili in modo oculato. In questo modo, puoi progettare esperienze di accesso con passkey sofisticate che gli utenti troveranno fluide e con le quali saranno più propensi a interagire.