Condividi tramite


Casi d'uso per passkey

In questo argomento vengono descritti alcuni casi d'uso per le passkey.

Caso d'uso 1: Bootstrapping

Bootstrap di un account sul Web.

1.1: Autenticazione dell'utente

Questa sezione si applica quando la relying party (RP) non conosce ancora chi controlla il dispositivo client. Non è disponibile alcun artefatto del browser per il provider di servizi di ripristino (ad esempio un cookie o un ID credenziale nella risorsa di archiviazione locale), anche se per il momento si presuppone che l'utente disponga di un account esistente con il punto di ripristino.

Per avviare un account, servire l'utente a una pagina di accesso.

Iniziare chiedendo all'utente l'identificatore dell'account; in genere un nome utente o un indirizzo di posta elettronica.

Accedere

Per supportare l'interfaccia utente di riempimento automatico per le passkey, assicurarsi di:

  1. Aggiungere il username valore e webauthn a tutte le annotazioni di completamento automatico esistenti nel campo di input del nome utente .
<div>
  <label for="username">Username:</label>
  <input name="username" id="loginform.username"
         autocomplete="username webauthn">
</div>
  1. Nel caricamento della pagina usare un'istruzione if per verificare se l'interfaccia utente di riempimento automatico (aggregazione condizionale) è disponibile, quindi chiamare navigator.credentials.get() con mediation: "conditional" e userVerification: "preferred".
  <script>
    (async () => {
      if (
      typeof window.PublicKeyCredential !== 'undefined'
      && typeof window.PublicKeyCredential.isConditionalMediationAvailable === 'function'
      ) {
        const available = await PublicKeyCredential.isConditionalMediationAvailable();

      if (available) {
          try {
            // Retrieve authentication options for `navigator.credentials.get()`
            // from your server.
            const authOptions = await getAuthenticationOptions();
      // This call to `navigator.credentials.get()` is "set and forget."
      // The Promise will resolve only if the user successfully interacts
      // with the browser's autofill UI to select a passkey.
      const webAuthnResponse = await navigator.credentials.get({
          mediation: "conditional",
      publicKey: {
          ...authOptions,
          // See note about userVerification below.
          userVerification: "preferred",
              }
            });
      // Send the response to your server for verification, and
      // authenticate the user if the response is valid.
      await verifyAutoFillResponse(webAuthnResponse);
          } catch (err) {
          console.error('Error with conditional UI:', err);
          }
        }
      }
    })();
  </script>

L'esempio precedente causerà l'errore seguente:

  • Recuperare le opzioni di autenticazione dal server. Restituisce almeno un valore casuale challenge e rpId da associare a questa richiesta di autenticazione.
  • Quando l'utente interagisce con il campo nome utente , il browser e la piattaforma verificheranno se esiste una passkey (nell'autenticatore della piattaforma) che può essere usata con la relying party.
  • In tal caso, la passkey verrà presentata all'utente come opzione per scegliere (insieme ad altre credenziali che possono essere compilate automaticamente, ad esempio i nomi utente archiviati nel gestore delle password del browser). Il browser o la piattaforma potrebbe eseguire il rendering di un'interfaccia utente simile a quella illustrata di seguito. Anche se l'aspetto esatto varia da una piattaforma o fattore di forma a un altro:

Accedere con passkey

  • Se l'utente seleziona la passkey, l'interfaccia utente della piattaforma guiderà l'utente tramite un controllo di verifica utente (spesso basato sulla biometria).
  • Se l'utente supera correttamente la verifica dell'utente, la navigator.credentials.get() chiamata ha esito positivo e restituisce una risposta WebAuthn.
  • Se l'utente seleziona una credenziale diversa da una passkey, il browser o la piattaforma sceglie un'azione appropriata diversa, ad esempio il riempimento automatico del nome utente, e la navigator.credentials.get() chiamata non viene risolta.
  • Se l'utente seleziona l'opzione "Passkey da un altro dispositivo" (il testo esatto varia leggermente in base alla piattaforma), il browser/piattaforma guiderà l'utente tramite una chiave di sicurezza FIDO2 o il flusso di autenticazione cross-device (CDA) per usare una passkey dal proprio smartphone o tablet per fornire una risposta WebAuthn alla navigator.credentials.get() chiamata.
  • Inviare la risposta WebAuthn al server per la verifica e controlli di sicurezza aggiuntivi. Se tutti i controlli hanno esito positivo, avviare una sessione autenticata per l'utente.

Questo è il motivo per cui si chiama interfaccia utente condizionale (o, più comunemente, l'interfaccia utente di riempimento automatico) di WebAuthn, ovvero l'interfaccia utente dell'autenticatore della piattaforma che guida l'utente attraverso la verifica o tramite il telefono, viene visualizzata solo se l'utente ha una passkey su questo dispositivo (o sceglie l'opzione "un altro dispositivo").

Come si può notare, in questa modalità la navigator.credentials.get() chiamata ha esito positivo o non è perché non viene mai risolta. Se ha esito positivo, il risultato della chiamata rivelerà sia un ID utente che un'asserzione WebAuthn firmata, che verrà usata dalla relying party (RP) per autenticare l'utente.

Se la chiamata non riesce, è necessario eseguire un'autenticazione utente legacy . Si otterrà un nome utente da questa prima pagina e nelle pagine successive verranno quindi soddisfatte ulteriori sfide di accesso(ad esempio password, risposta a problemi SMS e così via) all'utente. Questi potrebbero includere passaggi di ripristino dell'account nel caso in cui l'utente abbia dimenticato la password o non sia in grado di superare le normali sfide di accesso. Una volta superati tutti i problemi di accesso, l'utente viene considerato autenticato e connesso.

Quando l'utente non ha già un account con la relying party (RP), in genere si darà all'utente l'opzione nella pagina di accesso per creare un account. Se l'utente sceglie questa opzione, raccoglierai le informazioni necessarie da loro per aprire un nuovo account. Se l'utente apre correttamente un nuovo account, viene considerato anche autenticato e connesso.

Una volta effettuato l'accesso, l'utente potrebbe essere il momento di configurare una nuova passkey. Eseguire questa operazione per uno dei casi seguenti:

  • L'utente ha avviato il proprio account nel dispositivo passando problemi di accesso non passkey, ad esempio usando una password.
  • L'utente ha appena creato un nuovo account nella relying party (RP) e viene considerato connesso a causa di questo.
  • L'utente usava una passkey, ma usava un dispositivo diverso da quello in uso (selezionando "un altro dispositivo" illustrato nell'esempio precedente). Ciò può essere confermato esaminando l'attributo authenticatorAttachment nell'oggetto PublicKeyCredential restituito.

1.2: Autenticazione tra dispositivi

Se l'utente ha usato una passkey da un altro dispositivo (ad esempio un telefono, un tablet o una chiave di sicurezza FIDO2), la proprietà authenticatorAttachment nella risposta di autenticazione (getAssertion) avrà il valore cross-platform.

In questo scenario, offrire all'utente la scelta di creare una passkey nel dispositivo locale. Ciò comporterà un'esperienza utente più semplice in futuro, perché l'utente non dovrà usare l'altro dispositivo.

Configurare una passkey in questo dispositivo.

1.3: Nota sulla verifica dell'utente

Questo materiale sussidiario imposta userVerification su preferred, vale a dire che la verifica utente verrà tentata quando possibile.

Alcuni dispositivi, ad esempio computer desktop e portatili meno recenti, potrebbero non avere sensori biometrici. In tali dispositivi, se userVerification è impostato su required, all'utente potrebbe essere richiesto di immettere la password di accesso di sistema per ogni accesso usando una passkey. E questo può essere frustrante per loro.

Quando preferred viene usato, alcuni autenticatori della piattaforma richiedono sempre un controllo di verifica utente quando il dispositivo dispone di sensori biometrici, ma potrebbe ignorare la verifica utente nei dispositivi senza di essi.

Il risultato della verifica utente (trasmesso nei flag di dati dell'autenticatore) rifletterà il risultato effettivo della verifica utente e deve essere sempre convalidato in base ai requisiti del server.

1.4: Acconsentire esplicitamente l'utente a passkey

Prima di tutto, verificare che l'utente sia sufficientemente autenticato usando altri metodi di accesso, inclusa l'autenticazione a più fattori.

In secondo luogo, assicurarsi che la combinazione del dispositivo e del sistema operativo dell'utente supporti le passkey chiamando:

PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()

Se sono supportati passkey, verrà restituito true. Se non sono supportati, verrà restituito falsee sarà necessario interrompere il flusso di registrazione passkey.

Fornire un consenso esplicito o "upsell" modale/intermedio o pagina all'utente che le offre per creare una passkey:

Accesso più veloce e sicuro con passkey.

Suggerimento

Per garantire che l'utente conferi il consenso completamente informato, valutare la possibilità di mostrare (o collegare) descrizioni più lunghe che spiegano che tutti gli utenti che sono in grado di sbloccare il dispositivo corrente potranno accedere all'account nella relying party (RP).

Se l'utente acconsente, chiamare navigator.credentials.create() con le opzioni illustrate nell'esempio seguente:

navigator.credentials.create({
  publicKey: {
    rp: {
      // User-friendly name of your service.
      name: "Passkeys Developer",
      // Relying party (RP) identifier (hostname/FQDN).
      id: passkeys.contoso"
    },

    user: {
      // Persistent, unique identifier for the user account in your backend.
      id: Uint8Array.from("0525bc79-5a63-4e47-b7d1-597e25f5caba", c => c.charCodeAt(0)),
      // User-friendly identifier often displayed to the user (for example, email address).
      name: "amanda@contoso.com",
      // Human-readable display name, sometimes displayed by the client.
      displayName: "Amanda Brady"
    },
    // The challenge is a buffer of cryptographically random bytes generated on your backend,
    // and should be tightly bound to the current user session.
    challenge: Uint8Array.from("XZJscsUqtBH7ZB90t2g0EbZTZYlbSRK6lq7zlN2lJKuoYMnp7Qo2OLzD7xawL3s", c => c.charCodeAt(0)),
    pubKeyCredParams: [
      // An array of objects describing what public key types are acceptable to a server.
      {
        "type": "public-key",
        "alg": -7 // EC P256
      },
      {
        "type": "public-key",
        "alg": -257 // RSA
      }
    ],
    excludeCredentials: [
      // Array of credential IDs for existing passkeys tied to the user account.
      // This avoids creating a new passkey in an authenticator that already has 
      // a passkey tied to the user account.
      {
        // Example only.
        type: "public-key",
        id: new Uint8Array([21, 31, 56, ...]).buffer
      },
      {
        // Example only.
        type: "public-key",
        id: new Uint8Array([21, 31, 56, ...]).buffer
      }
    ],
    authenticatorSelection: {
      // Tells the authenticator to create a passkey.
      residentKey: "required",
      // Tells the client/authenticator to request user verification where possible;
      // for example, a biometric or a device PIN.
      userVerification: "preferred"
    },
    "extensions": {
      // Returns details about the passkey.
      "credProps": true
    }
  }
})

Nota

È consigliabile che la maggior parte delle relying party (RP) non specifichi il parametro attestation di trasporto dell'attestazione (per impostazione predefinita none) o usi in modo esplicito il valore indirect. Ciò garantisce l'esperienza utente più semplificata (è probabile che le piattaforme ottengano il consenso dall'utente per altri tipi di comunicazioni di attestazione, che probabilmente comportano una frazione maggiore di creazioni di credenziali non riuscite a causa dell'annullamento della creazione da parte degli utenti).

Quando la chiamata WebAuthn viene risolta, inviare la risposta al server e associare la chiave pubblica restituita e l'ID credenziale all'account utente autenticato in precedenza.

Caso d'uso 2: Riautenticazione

L'uso di passkey per una riautenticazione potrebbe essere necessario per uno dei motivi seguenti:

  • L'utente si è disconnesso e ora vuole eseguire di nuovo l'accesso.
  • La sessione utente è scaduta a causa dell'inattività e l'utente vuole eseguire di nuovo l'accesso.
  • L'utente sta per eseguire un'azione sensibile e deve riconfermare il controllo sulla sessione utente.

Per autenticare nuovamente l'utente in ognuna di queste situazioni, si useranno passkey configurati nel caso d'uso precedente. La chiamata API WebAuthn è la stessa in tutti e tre i casi, ma il trattamento dell'interfaccia utente fornito è leggermente diverso. Poiché l'account specifico viene specificato dall'utente, la piattaforma non richiederà all'utente di selezionare un account diverso nel servizio.

2.1: Azioni sensibili

Esaminiamo prima l'interfaccia utente per il terzo motivo, quando è il momento di autenticare nuovamente un'azione sensibile, verificare se si dispone di un ID credenziale per almeno una passkey per l'utente.

Se non è disponibile alcun ID credenziale di questo tipo, eseguire una richiesta di accesso tradizionale adatta per la riautenticazione, ad esempio:

Assicurarsi che si tratti di 1

Suggerimento

È consigliabile che in questa pagina di verifica di accesso gli utenti non possano modificare l'identificatore dell'account. Inoltre, la richiesta di accesso deve essere un elemento che un utente non autorizzato del dispositivo non può superare.

Se invece si trova almeno un ID credenziale passkey per l'utente, è possibile usare passkey per la riautenticazione:

Assicurarsi che si tratti di 2

Quando l'utente è pronto (nell'esempio precedente, quando fa clic sul pulsante "Vai"), chiama navigator.credentials.get(), passando tutti gli ID delle credenziali passkey dell'utente:

navigator.credentials.get({
  publicKey: {
    challenge: ...,
    rpId: ...,
     allowCredentials: [{
      type: "public-key",      
      id: new UInt8Array([21, 31, 56, ...]).buffer,
    }, {
      type: "public-key",
      id: new UInt8Array([21, 31, 56, ...]).buffer,
    }, {
      ...
    }],
    // see note below
    userVerification: "preferred", 
  }
});

Nota

Assicurarsi di leggere le indicazioni relative a userVerification del caso d'uso precedente.

Se invece l'utente fa clic su "Prova in un altro modo", è necessario offrirgli altri metodi di accesso (password e così via) per autenticarli nuovamente (presupponendo che l'utente disponga di altri metodi di accesso disponibili).

2.2: Sessioni scadute e disconnessione

A questo punto si esaminerà il caso in cui viene attivata la riautenticazione perché l'utente si è disconnesso o la relying party (RP) è scaduta la sessione dell'utente. Per facilitare questa operazione, il provider di servizi di ripristino deve mantenere una forma di stato della sessione utente che ricorda loro l'account precedentemente connesso, anche quando considerano l'utente disconnesso (che potrebbe essere ottenuto usando artefatti del browser, ad esempio cookie o archiviazione locale).

Nota

Una relying party (RP) potrebbe scegliere di considerare la disconnessione come un'azione completa e quindi eliminare tutti i riferimenti all'identità dell'utente. Tale rpo deve trattare un accesso successivo come un bootstrap dell'account e ripetere i passaggi illustrati in precedenza.

L'utente, come rpo, potrebbe quindi servire una pagina di accesso simile alla seguente:

Bentornato! 1

Se l'utente fa clic su "Usa un account diverso", è necessario immettere un flusso di bootstrap dell'account, come spiegato per il caso d'uso precedente, ripetendo i passaggi in cui la piattaforma consentirà all'utente di selezionare l'account che vuole usare.

Nota

In tal caso, è anche necessario concedere all'utente la possibilità di rimuovere completamente l'account suggerito dall'essere elencato nella pagina di accesso.

Tuttavia, se l'utente fa clic sul pulsante "Accedi come", verificare se all'utente è associato almeno un ID credenziale passkey. Se non è disponibile alcun ID credenziale, eseguire una richiesta di accesso tradizionale adatta per la riautenticazione, ad esempio:

Bentornato! 2

Se invece si trova almeno un ID credenziale passkey per l'utente, è possibile usare passkey per la riautenticazione:

Bentornato! 3

Quando l'utente è pronto (nell'esempio precedente, quando fa clic sul pulsante "Vai"), chiama navigator.credentials.get(), esattamente come già mostrato (ovvero passando tutti gli ID delle credenziali passkey dell'utente).

Se invece l'utente fa clic su "Prova in un altro modo", è necessario offrirgli altri metodi di accesso (password e così via) per autenticarli nuovamente (presupponendo che l'utente disponga di altri metodi di accesso disponibili).

Passaggi successivi

Vedere quindi Strumenti e librerie per passkey.

Altre informazioni