Cosa favorisce una buona esperienza di uscita?

Kenji Baheux
Kenji Baheux

Quando un utente esce da un sito web, comunica il suo desiderio di uscire completamente da un'esperienza utente personalizzata. È quindi importante aderire il più possibile al modello mentale dell'utente. Ad esempio, un'esperienza di uscita corretta dovrebbe tenere conto anche delle schede che l'utente potrebbe aver aperto prima di decidere di uscire.

La chiave per un'esperienza di logout ottimale può essere riassunta nella coerenza tra gli aspetti visivi e di stato dell'esperienza utente. Questa guida fornisce consigli concreti su cosa tenere presente e su come ottenere un'esperienza di uscita positiva.

Considerazioni principali

Quando implementi la funzionalità di logout sul tuo sito web, presta attenzione ai seguenti aspetti per garantire una procedura di logout fluida, sicura e intuitiva:

  • UX di uscita chiara e coerente: fornisci un pulsante o un link di uscita chiaro e visibile in modo coerente, facilmente identificabile e accessibile in tutto il sito web. Evita di utilizzare etichette ambigue o di nascondere la funzionalità di disconnessione in menu poco chiari, sottopagine o altre posizioni non intuitive.
  • Richiesta di conferma: implementa una richiesta di conferma prima di finalizzare la procedura di disconnessione. In questo modo, puoi evitare che gli utenti si disconnettano accidentalmente e puoi dare loro la possibilità di ripensarci se hanno davvero bisogno di uscire, ad esempio se bloccano diligentemente il dispositivo con una password complessa o un altro meccanismo di autenticazione.
  • Gestire più schede: se un utente ha aperto diverse pagine dello stesso sito web in schede diverse, assicurati che la disconnessione da una scheda aggiorni anche tutte le altre schede aperte del sito web.
  • Reindirizza a una pagina di destinazione sicura: dopo la disconnessione, reindirizza l'utente a una pagina di destinazione sicura che indichi chiaramente che non ha più eseguito l'accesso. Evita di reindirizzare gli utenti a pagine con informazioni personalizzate. Analogamente, assicurati che anche le altre schede non riflettano più uno stato di accesso. Inoltre, assicurati di non creare un reindirizzamento aperto di cui gli aggressori possano approfittare.
  • Pulizia della sessione: una volta che un utente è disconnesso, vengono rimossi completamente i dati sensibili della sessione utente, i cookie o i file temporanei associati alla sessione dell'utente. In questo modo, viene impedito l'accesso non autorizzato alle informazioni dell'utente o all'attività dell'account e il browser non potrà ripristinare le pagine con informazioni sensibili dalle varie cache, in particolare dalla cache di navigazione avanti/indietro.
  • Gestione degli errori e feedback: fornisci agli utenti messaggi di errore o feedback chiari in caso di problemi durante la disconnessione. Informalo di eventuali potenziali rischi per la sicurezza o fughe di dati se la procedura di disconnessione non va a buon fine.
  • Considerazioni sull'accessibilità: assicurati che il meccanismo di disconnessione sia accessibile agli utenti con disabilità, inclusi quelli che utilizzano tecnologie per la disabilità come gli screen reader o la navigazione con tastiera.
  • Compatibilità tra browser: testa la funzionalità di logout su browser e dispositivi diversi per assicurarti che funzioni in modo coerente e affidabile.
  • Monitoraggio e aggiornamenti continui: monitora regolarmente la procedura di disconnessione per rilevare eventuali potenziali vulnerabilità o falle di sicurezza. Implementa aggiornamenti e patch tempestivi per risolvere eventuali problemi identificati.
  • Federazione delle identità: se l'utente ha eseguito l'accesso utilizzando un'identità federata, verifica se è supportata e necessaria anche la disconnessione dal provider di identità. Inoltre, se il provider di identità supporta l'accesso automatico, non dimenticare di impedirlo.

DO

  • Se invalidi un cookie sul server nell'ambito di un flusso di disconnessione (o di altri flussi di revoca dell'accesso), assicurati di eliminare il cookie anche sul dispositivo dell'utente.
  • Elimina tutti i dati sensibili che potresti aver memorizzato sul dispositivo dell'utente: cookie, localStorage, sessionStorage, indexedDB, CacheStorage e qualsiasi altro archivio dati locale.
  • Assicurati che le risorse contenenti dati sensibili, in particolare i documenti HTML, vengano restituite con l'intestazione HTTP Cache-control: no-store in modo che il browser non le memorizzi in uno spazio di archiviazione permanente (ad esempio su disco). Analogamente, le chiamate XHR/fetch che restituiscono dati sensibili devono impostare anche l'intestazione HTTP Cache-Control: no-store per impedire la memorizzazione nella cache.
  • Assicurati che le schede aperte sul dispositivo dell'utente siano aggiornate con le revoche dell'accesso lato server.

Pulizia dei dati sensibili al momento della disconnessione

Al momento della disconnessione, ti consigliamo di cancellare i dati sensibili temporanei e archiviati localmente. L'attenzione ai dati sensibili è motivata dal fatto che l'eliminazione di tutto comporterebbe un'esperienza utente notevolmente peggiore, perché questo utente potrebbe tornare. Ad esempio, se dovessi cancellare tutti i dati memorizzati localmente, gli utenti dovranno accettare di nuovo le richieste di consenso per i cookie ed eseguire altre procedure come se non avessero mai visitato il tuo sito web.

Come eliminare i cookie

Nella risposta della pagina che conferma lo stato di disconnessione, allega intestazioni HTTP Set-Cookie per cancellare tutti i cookie correlati a dati sensibili o che li contengono. Imposta il valore expires su una data nel passato lontano e imposta il valore del cookie su una stringa vuota per sicurezza.

Set-Cookie: sensitivecookie1=; expires=Thu, 01 Jan 1970 00:00:00 GMT; secure
Set-Cookie: sensitivecookie2=; expires=Thu, 01 Jan 1970 00:00:00 GMT; secure
...

Scenario offline

Sebbene l'approccio descritto sopra sia sufficiente per i casi d'uso generali, non funziona se l'utente lavora offline. Ti consigliamo di richiedere due cookie per monitorare lo stato di accesso: un cookie sicuro solo HTTPS e un cookie normale accessibile tramite JavaScript. Se l'utente sta tentando di uscire mentre è offline, puoi cancellare il cookie JavaScript e procedere con altre operazioni di pulizia, se possibile. Se hai un worker di servizio, ti consigliamo di utilizzare anche l'API Background Fetch per riprovare una richiesta di eliminazione dello stato sul server quando l'utente sarà online in un secondo momento.

Come liberare spazio di archiviazione

Nella risposta della pagina che conferma lo stato di disconnessione, assicurati di ripulire i dati sensibili da vari datastore:

  • sessionStorage: anche se viene cancellato quando l'utente termina la sessione con il tuo sito web, ti consigliamo di ripulire in modo proattivo i dati sensibili quando l'utente si disconnette, nel caso in cui dimentichi di chiudere tutte le schede aperte sul tuo sito web.

    // Remove sensitive data from sessionStorage
    sessionStorage.removeItem('sensitiveSessionData1');
    // ...
    
    // Or if everything in sessionStorage is sensitive, clear it all
    sessionStorage.clear();
    
  • localStorage, indexedDB, API Cache/Service Worker: quando l'utente esce, ripulisci tutti i dati sensibili che potresti aver memorizzato utilizzando queste API, dato che questi dati rimangono invariati tra le sessioni.

    // Remove sensitive data from localStorage:
    localStorage.removeItem('sensitiveData1');
    // ...
    
    // Or if everything in localStorage is sensitive, clear it all:
    localStorage.clear();
    
    // Delete sensitive object stores in indexedDB:
    const name = 'exampleDB';
    const version = 1;
    const request = indexedDB.open(name, version);
    
    request.onsuccess = (event) => {
      const db = request.result;
      db.deleteObjectStore('sensitiveStore1');
      db.deleteObjectStore('sensitiveStore2');
    
      // ...
    
      db.close();
    }
    
    // Delete sensitive resources stored via the Cache API:
    caches.open('cacheV1').then((cache) => {
      await cache.delete("/personal/profile.png");
    
      // ...
    }
    
    // Or better yet, clear a cache bucket that contains sensitive resources:
    caches.delete('personalizedV1');
    

Come svuotare le cache

  • Cache HTTP: se imposti Cache-control: no-store sulle risorse con dati sensibili, la cache HTTP non conserverà nulla di sensibile.
  • Cache di navigazione avanti/indietro: analogamente, se hai seguito i consigli relativi a Cache-control: no-store e all'eliminazione dei cookie sensibili (ad esempio, cookie sicuri solo HTTPS correlati all'autenticazione) quando gli utenti escono, non devi preoccuparti che i dati sensibili vengano conservati nella cache di navigazione avanti/indietro. Infatti, la funzionalità della cache back/forward elimina le pagine dello stesso origine pubblicate con un'intestazione HTTP Cache-control: no-store se rileva uno o più dei seguenti indicatori:
    • Uno o più cookie sicuri solo HTTPS sono stati modificati o eliminati.
    • Una o più risposte per le chiamate XHR/fetch, inviate dalla pagina, includevano l'intestazione HTTP Cache-control: no-store.

Esperienza utente coerente tra le schede

Gli utenti potrebbero aver aperto molte schede del tuo sito web prima di decidere di uscire. A quel punto, potrebbe aver dimenticato altre schede o persino altre finestre del browser. È meglio evitare di fare affidamento sugli utenti per chiudere tutte le schede e le finestre pertinenti. Assicurati invece che lo stato di accesso dell'utente sia coerente tra le schede.

Istruzioni

Per ottenere uno stato di accesso coerente tra le schede, ti consigliamo di utilizzare una combinazione di eventi pageshow/pagehide e l'API Broadcast Channel.

  • Evento pageshow: in caso di pageshow persistente, controlla lo stato di accesso dell'utente ed elimina i dati sensibili o addirittura l'intera pagina se l'utente non ha più eseguito l'accesso. Tieni presente che l'evento pageshow si attiverà prima che la pagina venga visualizzata per la prima volta dopo essere stata ripristinata da una navigazione a ritroso/avanti, il che garantisce che il controllo dello stato di accesso ti consenta di reimpostare la pagina su uno stato non sensibile.

    window.addEventListener('pageshow', (event) => {
      if (event.persisted && !document.cookie.match(/my-cookie)) {
        // The user has logged out.
        // Force a reload, or otherwise clear sensitive information right away.
        body.innerHTML = '';
        location.reload();
      }
    });
    
  • L'API Broadcast Channel: utilizza questa API per comunicare le modifiche dello stato di accesso tra schede e finestre. Se l'utente è disconnesso, cancella tutti i dati sensibili oppure reindirizza a una pagina di disconnessione in tutte le schede e le finestre con dati sensibili.

    // Upon logout, broadcast new login state so that other tabs can clean up too:
    const bc = new BroadcastChannel('login-state');
    bc.postMessage('logged out');
    
    // [...]
    const bc = new BroadcastChannel('login-state');
    bc.onMessage = (msgevt) => {
      if (msgevt.data === 'logged out') {
        // Clean up, reload or navigate to the sign-out page.
        // ...
      }
    }
    

Conclusione

Se segui le indicazioni riportate in questo documento, potrai progettare un'esperienza utente di logout ottimale che impedisca i logout involontari e protegga le informazioni personali dell'utente.