Uma das principais preocupações dos desenvolvedores de front-end é estabelecer uma estrutura de autorização e autenticação segura e rápida. Também em destaque está a experiência do usuário, que é muito afetada pelo processo de autenticação.
Você se lembra da última vez que inseriu as credenciais de login no Google, Facebook, LinkedIn ou algum outro aplicativo ou site? Provavelmente não. Isso ocorre porque muitos aplicativos e serviços da web hoje em dia usam login persistente para fornecer uma experiência de usuário tranquila.
Neste tutorial, mostraremos como usar tokens de atualização no React para facilitar sessões de login infinitamente longas. Abordaremos o seguinte:
O que é um token de atualização? O que é a rotação do token de atualização? O que é detecção de reutilização do token de atualização? Onde armazenar tokens de atualização Configurando um aplicativo React com login persistente usando rotação de token de atualização
O que é um token de atualização?
Em termos simples, um token de acesso permite que os usuários obtenham recursos do seu aplicativo.
Por motivos de segurança, os tokens de acesso geralmente têm uma vida muito curta. Quando um token de acesso expira, um token de atualização pode ser usado para obter um novo token de acesso sem inserir as credenciais de login novamente.
Os tokens de atualização têm uma vida útil longa. Se eles forem válidos e não expirados, os clientes podem obter novos tokens de acesso. Essa longa vida útil pode levar à vulnerabilidade de recursos protegidos.
O que é rotação de token de atualização?
A rotação de token de atualização é uma técnica para proteger tokens de atualização. Quando um novo token de acesso é solicitado com o token de atualização, um novo token de atualização também é retornado e o antigo é invalidado. O objetivo da atualização de rotação de tokens é eliminar a vulnerabilidade risco representado por tokens de atualização de longa duração.
Até recentemente, o uso de tokens de atualização não era recomendado em aplicativos da web de página única (ao contrário dos aplicativos móveis) porque os SPAs não têm mecanismo seguro para armazenar tokens. A rotação de atualização e a detecção de reutilização de token de atualização (que veremos mais tarde) aumentam a segurança dessas informações de alto valor.
O diagrama a seguir explica como funciona o mecanismo de rotação de token de atualização. Você pode aceitar Auth0 como um provedor de identidade:
Atualizar mecanismo de rotação do token (fonte: https://auth0.com/docs/tokens/refresh-tokens/refresh-token-rotation )
O que é detecção de reutilização de token de atualização?
A detecção de reutilização de token de atualização é um mecanismo que suporta rotação de token de atualização. Quando um token de acesso expira, o cliente obtém um novo conjunto de tokens (token de acesso e atualização) usando um token de atualização. Em seguida, o provedor de identidade invalida imediatamente o token de atualização anterior.
Se o provedor de identidade detectar o uso desse token de atualização invalidado, ele invalida imediatamente todos os tokens de atualização e acesso, fazendo com que o cliente se autentique usando credenciais de login novamente. Esse mecanismo impede que seu aplicativo contra ataques maliciosos quando há vazamento de tokens.
Os dois casos a seguir da documentação do Auth0 são bons exemplos dos possíveis cenários para esses ataques e como funciona a detecção de reutilização de token de atualização:
Cenário 1 do mecanismo de detecção de reutilização de token de atualização
Cenário 2 do mecanismo de detecção de reutilização de token de atualização
Onde armazenar tokens de atualização
Existem várias maneiras de armazenar tokens em sessões de cliente: na memória, por meio de autenticação silenciosa e no armazenamento local do navegador.
Armazenando tokens na memória
Você pode armazenar tokens de atualização na memória. No entanto, esse armazenamento não persistirá nas atualizações de página ou nas novas guias. Portanto, os usuários devem inserir credenciais de login a cada atualização de página ou em novas guias, o que afeta negativamente a experiência do usuário.
Autenticação silenciosa
O armazenamento de tokens de atualização por meio de autenticação silenciosa envolve o envio de uma solicitação para o servidor de identidade para obter um token de acesso sempre que houver uma solicitação de API ou durante a atualização da página. Se sua sessão ainda permanecer, o provedor de identidade retornará um token válido. Caso contrário, ele redireciona você para a página de login.
Esta é uma estrutura muito mais segura, no entanto: sempre que o cliente envia uma solicitação de autenticação silenciosa, ele bloqueia o aplicativo. Isso pode ser na renderização da página ou durante uma chamada de API.
Além disso, tive comportamentos indesejados, como loops de login, no modo anônimo.
Armazenamento de tokens localmente
A prática sugerida para login persistente é armazenar tokens no armazenamento local do navegador. O armazenamento local fornece dados persistentes entre as atualizações de página e várias guias.
Embora o armazenamento de tokens de atualização localmente não elimine totalmente a ameaça de ataques de script entre sites (XSS), ele reduz significativamente essa vulnerabilidade a um nível aceitável nível. Ele também melhora a experiência do usuário, tornando o aplicativo executado com mais facilidade.
Configurando um aplicativo React com login persistente usando a rotação de token de atualização
Para demonstrar como funcionam os tokens de atualização e a rotação de token de atualização, vamos configurar um mecanismo de autenticação do app react com um token de atualização. Usaremos Auth0 para atualização de rotação de token e detecção de reutilização de token de atualização. Auth0 é uma das plataformas de autenticação e autorização mais populares.
Para integrar Auth0 em nosso aplicativo React, usaremos auth0-react para conectar o aplicativo com Auth0 e um gancho chamado useAuth0 para obter o estado e métodos de autenticação. No entanto, é um desafio alcançar estados e métodos de autenticação fora dos componentes.
Portanto, transformei a biblioteca @ auth0/auth0-spa-js , que é outra biblioteca cliente oficial do Auth0, para ter um gancho de autenticação e métodos que podem ser acessíveis fora dos componentes.
I criou um arquivo auth0.tsx (você pode ir com JSX, é claro) como este:
import React, {useState, useEffect, useContext, createContext} de’react’; import createAuth0Client, {getIdTokenClaimsOptions, GetTokenSilentlyOptions, GetTokenWithPopupOptions, IdToken, LogoutOptions, PopupLoginOptions, RedirectLoginOptions,} de’@ auth0/auth0-spa-js’; importar Auth0Client de’@ auth0/auth0-spa-js/dist/typings/Auth0Client’; import {config} de’../config’; importar histórico de’../history’; importar {urls} de’../routers/urls’; interface Auth0Context {isAuthenticated: boolean; usuário: qualquer; carregando: booleano; popupOpen: boolean; loginWithPopup (opções: PopupLoginOptions): Promessa
Como você pode ver na linha 44, cacheLocation é definido como localStorage, useRefreshToken é definido como true e offline_access é adicionado ao escopo.
No arquivo App.tsx principal, você deve importar o Auth0Provider HOC para envolver todas as rotas.
Eu também queria ter certeza sobre cada solicitação de API enviada com um token válido. Mesmo que a resposta da API diga não autorizado, ela redireciona o cliente para a página de autenticação.
Usei os interceptores do Axios, que permitem inserir lógica antes de enviar solicitações ou obter uma resposta.
//Interceptador de solicitação para chamadas de API axios.interceptors.request.use (async config=> {const token=await getTokenSilently (); config.headers.authorization=`Bearer $ {token}`; return config;}, erro=> { Promise.reject (erro);});//Interceptador de resposta para chamadas de API axios.interceptors.response.use (response=> {return response.data;}, função assíncrona (erro) {if (error.response?.Status===401 || erro?.Error===’login_required’) {history.push (urls.authentication);} return Promise.reject (erro);});
O componente da página de autenticação inclui apenas o método loginWithRedirect, que redireciona os clientes para a página de login do Auth0 e, em seguida, redireciona para a página desejada.
import React, {useEffect} from’react’; import {useAuth0} de’../../../auth/auth0′; importar {urls} de’../../../routers/urls’; Login const: React.FC=()=> {const {loginWithRedirect, carregando}=useAuth0 (); useEffect (()=> {if (! carregando) {loginWithRedirect ({appState: urls.orderManagement});}}, [carregando]); return null; }; exportar Login padrão; Atualizar as configurações de rotação do token também devem ser definidas no painel do Auth0.
Vá para o seu aplicativo no painel do Auth0. Nas configurações, você verá a configuração Atualizar rotação do token . Ligue a rotação e defina o intervalo de reutilização, que é o intervalo durante o qual o algoritmo de detecção de reutilização do token de atualização não funcionará.
É isso aí! Agora, nosso aplicativo possui um sistema de autenticação persistente e seguro. Isso tornará seu aplicativo mais seguro e melhorará a experiência do usuário para inicializar.
Agradecimentos especiais ao meu colega Turhan Gür que me apoiam nesta jornada, fornecendo feedback crucial.