Como sair
Quando um usuário sai de um site, ele comunica o desejo de sair completamente de uma experiência de usuário personalizada. Por isso, é importante aderir o mais próximo possível do modelo mental do usuário. Por exemplo, uma experiência de logout adequada também deve levar em conta quaisquer guias que o usuário possa ter aberto antes de decidir sair.
A chave para uma ótima experiência de logout pode ser resumida na consistência entre os aspectos visuais e de estado da experiência do usuário. Este guia fornece conselhos concretos sobre o que prestar atenção e como obter uma boa experiência de logout.
Principais considerações
Ao implementar a funcionalidade de logout em seu site, preste atenção aos seguintes aspectos para garantir um processo tranquilo, seguro e intuitivo:
- UX de logout clara e consistente: forneça um botão ou link de saída claro e consistente, que seja facilmente identificável e acessível em todo o site. Evite usar marcadores ambíguos ou ocultar a funcionalidade de logout em menus, subpáginas ou outros locais obscuros.
- Prompt de confirmação: implemente uma solicitação de confirmação antes de finalizar o processo de logout. Isso ajuda a evitar que os usuários saiam acidentalmente e reavalie se é realmente necessário sair, por exemplo, se bloquearem o dispositivo com uma senha forte ou outro mecanismo de autenticação.
- Processar várias guias: se um usuário abrir várias páginas do mesmo site em guias diferentes, verifique se, ao sair de uma guia, todas as outras do site também serão atualizadas.
- Redirecione 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 um estado de login. Além disso, certifique-se de não estar criando um redirecionamento aberto que possa ser aproveitado por invasores.
- Limpeza de sessão: depois que um usuário sair, remova completamente os dados confidenciais da sessão, os cookies ou os arquivos temporários associados à sessão do usuário. Isso impede o acesso não autorizado a informações do usuário ou atividade da conta e também impede que o navegador restaure páginas com informações sensíveis dos vários caches, especialmente 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 os usuários sobre possíveis riscos de segurança ou vazamentos de dados se o processo de logout falhar.
- Considerações de acessibilidade: verifique se o mecanismo de saída é acessível a usuários com deficiências, incluindo aqueles que usam tecnologias adaptativas, como leitores de tela ou navegação pelo teclado.
- Compatibilidade entre 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 para identificar possíveis vulnerabilidades ou falhas de segurança. Implemente atualizações e patches oportunos para resolver os problemas identificados.
- Federação de identidade: se o usuário tiver feito login usando uma identidade federada, confira se é necessário e também é possível sair do provedor de identidade. Além disso, se o provedor de identidade for compatível com o login automático, não se esqueça de impedir isso.
O que fazer
- Se você invalidar um cookie no servidor como parte de um fluxo de logout (ou outros fluxos de revogação de acesso), não esqueça também de excluir o cookie do dispositivo do usuário.
- Limpe todos os dados confidenciais que você armazenou no dispositivo do usuário: cookies, localStorage, sessionStorage, indexedDB, CacheStorage e todos os outros armazenamentos de dados locais.
- Verifique se todos os recursos que contêm dados sensíveis, em determinados 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, chamadas XHRs/fetch
que retornam dados sensíveis também precisam definir o cabeçalho HTTPCache-Control: no-store
para evitar qualquer armazenamento em cache. - Verifique se as guias abertas no dispositivo do usuário estão atualizadas com revogações de acesso do lado do servidor.
Como limpar dados sensíveis ao sair
Ao sair, limpe os dados confidenciais temporários e armazenados localmente. O foco nos 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ê apagar todos os dados armazenados localmente, os usuários vão precisar confirmar novamente as solicitações de consentimento para o uso de cookies e passar por outros processos como se nunca tivessem visitado seu site.
Como limpar cookies
Na resposta da página que confirma o status de logout, anexe cabeçalhos HTTP Set-Cookie
para limpar todos os cookies relacionados ou que contenham dados sensíveis. Defina o valor de expires
como uma data no passado distante e configure o valor do cookie como uma string vazia para uma boa medida.
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 funciona quando o usuário está trabalhando off-line. É recomendável considerar a exigência de dois cookies para rastrear o estado de login: um cookie somente HTTPS seguro e um normal acessível via JavaScript. Se o usuário estiver tentando sair enquanto estiver off-line, você pode limpar o cookie JavaScript e prosseguir com outras operações de limpeza, se possível. Se você tiver um service worker, também poderá aproveitar a API Background Fetch para repetir uma solicitação para limpar o estado no servidor quando o usuário estiver on-line mais tarde.
Como liberar espaço de armazenamento
Na resposta da página que confirma o estado desconectado, limpe os dados sensíveis de vários repositórios de dados:
sessionStorage: embora isso seja apagado quando o usuário encerrar a sessão com seu site, considere limpar proativamente os dados sensíveis quando o usuário sair, caso ele se esqueça de fechar todas as guias abertas no seu 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 sensíveis que você possa ter armazenado usando essas APIs, já que eles vão persistir entre 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 reterá nada sensível. - Cache de avanço e retorno: da mesma forma, se você tiver seguido 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, você não vai precisar 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 páginas de mesma origem veiculadas com um cabeçalho HTTPCache-control: no-store
se observar um ou mais dos seguintes indicadores:- Um ou mais cookies somente HTTPS seguros foram modificados ou excluídos.
- Uma ou mais respostas para chamadas XHRs/
fetch
, emitidas pela página, incluíam o cabeçalho HTTPCache-control: no-store
.
Experiência do usuário consistente em todas as guias
É possível que os usuários tenham aberto muitas guias no site antes de decidirem sair. A essa altura, eles podem ter esquecido as outras guias ou até mesmo outras janelas do navegador. É melhor evitar depender de seus usuários fechar todas as guias e janelas relevantes. Em vez disso, assuma 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
pageshow
: após umapageshow
persistente, verifique o status de login do usuário e limpe os dados sensíveis, ou até mesmo a página inteira, caso ele não esteja mais conectado. O eventopageshow
será acionado antes da página ser renderizada pela primeira vez depois de ser restaurada de uma navegação de avanço e retorno. Isso garante que a verificação de estado de login permita 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 as mudanças de estado de login em guias e janelas. Se o usuário estiver desconectado, limpe todos os dados sensíveis ou redirecione-o para uma página de saída em todas as guias e janelas com dados confidenciais.
// 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
Ao seguir as orientações neste documento, você poderá criar uma ótima experiência de usuário de logout, que evite saídas acidentais e proteja suas informações pessoais.