Approfondimento sulle credenziali rilevabili

Sebbene le credenziali FIDO come le passkey abbiano lo scopo di sostituire le password, la maggior parte di queste può anche liberare l'utente dalla necessità di digitare un nome utente. In questo modo, gli utenti possono autenticarsi selezionando un account da un elenco di passkey che hanno per il sito web corrente.

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 token di sicurezza moderno.

Per assicurarti che le tue credenziali vengano create come passkey (credenziali rilevabili), specifica residentKey e requireResidentKey quando vengono create le credenziali.

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 delle passkey disponibili, identificate dal Proprietà user.name impostata al momento della creazione. Se l'utente ne seleziona una, user.id verrà incluso nella firma risultante. Il server può quindi utilizzare l'ID credenziale restituito per cercare l'account invece di 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 è possibile crearlo, viene restituito NotSupportedError.
  • 'preferred': la parte soggetta a limitazioni 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 conservata per la compatibilità con le versioni precedenti di WebAuthn Level 1, una versione precedente della specifica. Imposta questo valore su true se residentKey è 'required', altrimenti impostalo su false.

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:

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. Questa opzione è adatta al flusso di autenticazione passkey avviato premendo un pulsante dedicato all'autenticazione 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;
  
  // ...
}

Mostra la compilazione automatica dei moduli tramite passkey

Il selettore modale dell'account descritto sopra funziona bene se la maggior parte degli utenti utilizza passkey che sono disponibili sul dispositivo locale. Per un utente che non ha passkey locali, la finestra di dialogo modale viene comunque visualizzata e gli viene chiesto di presentare una passkey da un altro dispositivo. Durante la transizione degli utenti alle passkey, potresti voler evitare questa UI per gli utenti che non l'hanno configurata.

La selezione di una passkey può essere aggiunta alle richieste di compilazione automatica per i campi di un modulo di accesso tradizionale, insieme a nomi utente e password salvati. In questo modo, un utente con passkey può "compilare" il modulo di accesso selezionando la propria passkey, gli utenti con coppie nome utente/password salvate possono selezionarle, mentre gli utenti che non hanno nessuno dei due possono comunque digitare nome utente e password.

Questa esperienza utente è ideale quando la parte soggetta a limitazioni è in una migrazione con un utilizzo misto di password e passkey.

Per ottenere questa esperienza utente, oltre a passare un array vuoto alla proprietà allowCredentials o omettere il parametro, specifica mediation: 'conditional' su navigator.credentials.get() e annota un campo di immissione HTML username 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 si risolve mai.

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" ...>

Puoi scoprire come creare questa esperienza utente nella pagina Accedere con una passkey tramite la compilazione automatica dei moduli e nel codelab Implementare le passkey con la compilazione automatica dei moduli in un'app web.

Riautenticazione

In alcuni casi, ad esempio quando si utilizzano le passkey per la re-autenticazione, 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) con una credenziale valida.

Per offrire questa esperienza utente, fornisci un elenco di ID credenziali per l'utente che esegue l'accesso. La parte soggetta a limitazioni deve 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 di trasporti supportati dal dispositivo che contiene questa credenziale, utilizzato dai browser per ottimizzare la UI che chiede all'utente di presentare un dispositivo esterno. Questo elenco, se fornito, deve contenere il risultato della chiamata a getTransports() durante la registrazione di ciascuna credenziale.

Riepilogo

Le credenziali rilevabili rendono l'esperienza di accesso tramite passkey molto più facile da usare, in quanto consentono di saltare l'inserimento di un nome utente. Con la combinazione di residentKey, requireResidentKey e allowCredentials, le parti soggette a limitazioni possono ottenere 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 sofisticate esperienze di accesso tramite passkey che gli utenti troveranno senza problemi e con cui saranno più propensi a interagire.