O que resulta em uma boa experiência de logout?

Kenji Baheux
Kenji Baheux

Saída

Quando um usuário sai de um site, ele está comunicando o desejo de sair completamente de uma experiência do usuário personalizada. Por isso, é importante aderir o máximo possível ao modelo mental do usuário. Por exemplo, uma experiência adequada de logout também deve considerar as guias que o usuário abriu antes de sair.

O segredo para uma ótima experiência de logout pode ser resumido em vários aspectos visuais e de estado da experiência do usuário. Este guia oferece conselhos concretos sobre o que prestar atenção e como ter uma boa experiência de logout.

Principais considerações

Ao implementar a funcionalidade de logout no seu site, preste atenção aos seguintes aspectos para garantir um processo de logout tranquilo, seguro e intuitivo:

  • UX clara e consistente: ofereça um botão ou link claro e consistente para sair, que seja facilmente identificável e acessível em todo o site. Evite usar rótulos ambíguos ou ocultar a funcionalidade de saída em menus, subpáginas ou outros locais não intuitivos.
  • Comando de confirmação: implemente um comando de confirmação antes de finalizar o processo de logout. Isso ajuda a evitar que os usuários saiam acidentalmente e permite que eles reconsiderem se realmente precisam sair da conta, por exemplo, se eles bloquearem o dispositivo com uma senha forte ou outro mecanismo de autenticação.
  • Lidar com várias guias: se um usuário abriu várias páginas do mesmo site em guias diferentes, verifique se sair de uma guia atualiza todas as outras guias abertas do site também.
  • Redirecionar para uma página de destino segura: após sair, redirecione o usuário para uma página de destino segura que indique claramente que ele não está mais conectado. Evite redirecionar os usuários para páginas que tenham informações personalizadas. Da mesma forma, verifique se as outras guias também não refletem mais o estado conectado. Além disso, certifique-se de não criar um redirecionamento aberto que possa ser aproveitado por invasores.
  • Limpeza de sessão: depois que um usuário sair, remova completamente todos os dados confidenciais da sessão, cookies ou arquivos temporários associados à sessão do usuário. Isso impede o acesso não autorizado às informações do usuário ou à atividade da conta, além de impedir que o navegador restaure páginas com informações sensíveis dos vários caches, principalmente do cache de avanço e retorno.
  • Tratamento de erros e feedback: forneça mensagens de erro claras ou feedback aos usuários se houver algum problema quando eles saírem. Informe sobre possíveis riscos de segurança ou vazamentos de dados se o processo de logout falhar.
  • Considerações sobre acessibilidade: garanta que o mecanismo de saída seja acessível para usuários com deficiências, incluindo aqueles que usam tecnologias adaptativas, como leitores de tela ou navegação pelo teclado.
  • Compatibilidade com vários navegadores: teste a funcionalidade de saída em diferentes navegadores e dispositivos para garantir que ela funcione de maneira consistente e confiável.
  • Monitoramento e atualizações contínuos: monitore regularmente o processo de saída em busca de possíveis vulnerabilidades ou brechas de segurança. Implementar atualizações e patches oportunos para resolver os problemas identificados.
  • Federação de identidade: se o usuário fez login com uma identidade federada, confira se também é compatível e necessário sair do provedor de identidade. Além disso, se o provedor de identidade oferecer suporte ao login automático, não se esqueça de impedi-lo.

O QUE FAZER

  • Se você invalidar um cookie no servidor como parte de um fluxo de logout (ou de outros fluxos de revogação de acesso), ele também precisa ser excluído do dispositivo do usuário.
  • Limpe todos os dados confidenciais que você possa ter armazenado no dispositivo do usuário: cookies, localStorage, sessionStorage, indexedDB, CacheStorage e qualquer outro armazenamento de dados local.
  • Verifique se todos os recursos que contêm dados sensíveis, especialmente documentos HTML, são retornados com o cabeçalho HTTP Cache-control: no-store para que o navegador não armazene esses recursos no armazenamento permanente (por exemplo, no disco). Da mesma forma, as chamadas XHRs/fetch que retornam dados sensíveis também precisam definir o cabeçalho HTTP Cache-Control: no-store para evitar armazenamento em cache.
  • Verifique se as guias abertas no dispositivo do usuário estão atualizadas com a revogação de acesso do lado do servidor.

Como limpar dados sensíveis ao sair

Ao sair, considere limpar os dados sensíveis temporários e armazenados localmente. O foco em dados sensíveis é motivado pelo fato de que limpar tudo resultaria em uma experiência do usuário significativamente pior, porque esse usuário pode muito bem voltar. Por exemplo, se você limpar todos os dados armazenados localmente, os usuários terão que confirmar novamente as solicitações de consentimento de cookies e passar por outros processos como se nunca tivessem acessado seu site.

Como limpar cookies

Na resposta da página que confirma o status de usuário desconectado, anexe cabeçalhos HTTP Set-Cookie para limpar todos os cookies relacionados ou que contêm dados confidenciais. Defina o valor expires como uma data no passado distante e defina o valor do cookie como uma string vazia para uma boa medição.

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

Cenário off-line

Embora a abordagem descrita acima seja suficiente para casos de uso gerais, ela não funcionará se o usuário estiver trabalhando off-line. É recomendável exigir dois cookies para rastrear o estado de login: um cookie seguro somente HTTPS e um cookie normal acessível via JavaScript. Se o usuário estiver tentando sair enquanto estiver off-line, limpe o cookie JavaScript e prossiga com outras operações de limpeza, se possível. Se você tem um service worker, também pode aproveitar a API Background Fetch para repetir uma solicitação para limpar o estado no servidor quando o usuário ficar on-line mais tarde.

Como liberar espaço de armazenamento

Na resposta da página que confirma o estado de logout, limpe os dados confidenciais de vários repositórios de dados:

  • sessionStorage: embora essa opção seja apagada quando o usuário encerra a sessão no seu site, recomendamos limpar proativamente os dados sensíveis quando o usuário sai, caso ele se esqueça de fechar todas as guias abertas no site.

    // Remove sensitive data from sessionStorage
    sessionStorage.removeItem('sensitiveSessionData1');
    // ...
    
    // Or if everything in sessionStorage is sensitive, clear it all
    sessionStorage.clear();
    
  • APIs localStorage, indexedDB, Cache/Service Worker: quando o usuário sair, limpe todos os dados confidenciais que você possa ter armazenado usando essas APIs, já que esses dados persistiriam em todas as sessões.

    // 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');
    

Como limpar caches

  • Cache HTTP: desde que você defina Cache-control: no-store em recursos com dados confidenciais, o cache HTTP não vai reter nada confidencial.
  • Cache de avanço e retorno: da mesma forma, se você seguiu as recomendações sobre Cache-control: no-store e a limpeza de cookies sensíveis (por exemplo, cookies seguros somente HTTPS relacionados à autenticação) quando os usuários saírem, não vai ser necessário se preocupar com a retenção de dados sensíveis no cache de avanço e retorno. De fato, o recurso de cache de avanço e retorno vai remover as páginas de mesma origem veiculadas com um cabeçalho HTTP Cache-control: no-store se observarem um ou mais dos seguintes sinais:
    • Um ou mais cookies exclusivos para HTTPS foram modificados ou excluídos.
    • Uma ou mais respostas para chamadas XHRs/fetch, emitidas pela página, incluíam o cabeçalho HTTP Cache-control: no-store.

Experiência do usuário consistente em várias guias

Talvez os usuários tenham aberto várias guias no seu site antes de decidir sair. A essa altura, eles podem ter se esquecido de outras guias ou até mesmo de outras janelas do navegador. É melhor não depender de seus usuários para fechar todas as guias e janelas relevantes. Em vez disso, adote uma postura proativa, garantindo que o estado de login do usuário seja consistente em todas as guias.

Orientações

Para alcançar um estado de login consistente em todas as guias, use uma combinação de eventos pageshow/pagehide e a API Broadcast Channel.

  • Evento do pageshow: após uma pageshow persistente, verifique o status de login do usuário e limpe os dados sensíveis ou até mesmo a página inteira, caso o usuário não esteja mais conectado. O evento pageshow será acionado antes da renderização da página pela primeira vez após a restauração de uma navegação de avanço e retorno. Isso garante que a verificação de estado do login permitirá redefinir a página para um estado não confidencial.

    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();
      }
    });
    
  • API Broadcast Channel: use essa API para comunicar mudanças no estado de login entre guias e janelas. Se o usuário estiver desconectado, limpe todos os dados sensíveis ou redirecione para uma página de logout em todas as guias e janelas com dados sensíveis.

    // 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.
        // ...
      }
    }
    

Conclusão

Siga as orientações neste documento para criar uma ótima experiência de usuário desconectado, que evita logout não intencional e protege as informações pessoais do usuário.