Atualmente, o esquema de segurança que estabelece dois tokens é bastante comum. Há muitas informações sobre o tema na Internet. Geralmente, há apenas uma descrição do que são os tokens de Atualização e Acesso e como usar.
Para entender o conceito por trás dos tokens, gostaria de fazer um experimento simples.
Vamos imaginar que você é um estudante que gosta de dinheiro, mas geralmente tem cerca de zero no saldo da conta dele.
No caminho para sua universidade, você abre o aplicativo móvel do banco para verificar o saldo da sua conta.
Para mostrar a você que um aplicativo de saldo precisa executar uma solicitação ao servidor do banco:
GET http://api.mybank.com/balance HTTP 1.1
e recebe resposta
{ balance: '$0.0' }

Seria bom se ninguém, exceto você, pudesse verificar sua conta bancária. Para fazer isso, vamos adicionar um cabeçalho especial com nome de usuário e sua senha exclusiva:
`Autorização: Nome de usuário Senha
Autorização: JohnDwayson QWERTY1`
Agora, o servidor pode autenticá-lo com seu nome de usuário e senha pessoais. Isso significa que o par JohnDwayson QWERTY1 precisa ser mantido em um local secreto no seu telefone celular para ser protegido de alguém que não tem permissão para gastar seu dinheiro. Seria ainda melhor se pudéssemos evitar o armazenamento de senha, mas ninguém quiser inseri-la com muita frequência.
Quando estamos usando nosso aplicativo móvel por 30 minutos em um ônibus, ele envia sua senha pela rede várias vezes em 30 minutos.

Todo requset contém senha
Vamos continuar nosso experimento mental. Você ainda está em um ônibus e seu aplicativo envia uma solicitação ao servidor.
E se uma fraude estiver ao seu redor em um ônibus e ele puder interceptar um ou alguns pacotes http do seu celular para o servidor do banco?
Se o aplicativo atualizar informações a cada minuto, a fraude terá 30 possibilidades para cruzar solicitações e obter sua senha.
Vamos supor que ele roubou de 5 a 6 mensagens. Sua senha agora está comprometida e a fraude pode usá-la para acessar as informações da sua conta.

O homem do meio pode ouvir a senha
O que ele pode fazer com essa informação? Boas notícias de que ele não pode gastar seu dinheiro porque você ainda não o tem ... ainda :) Ele também não pode alterar sua senha, pois nesse caso você notará isso e poderá usar o SMS de um banco para recuperar a senha. A senha antiga roubada nesse caso não será mais válida e o aluno economizará seu dinheiro
Mas o que ele pode fazer é continuar verificando seu saldo em paralelo com você. Ele pode escrever facilmente um script Python que verificará sua conta a cada 10 segundos e, assim que você receber dinheiro, ele poderá gastar cada centavo comprando bitcoins. Provavelmente ainda pior, se o roteiro dele gastar entre 5 e 10 buks todos os dias, e provavelmente não será notado por meses ou anos.

Hacker espera pelo seu dinheiro
Para evitar isso, podemos pedir ao usuário para alterar sua senha depois de algum tempo. Digamos que a senha seja válida por 3 meses. O bom é que, após três meses, ele perderá o acesso à sua conta. O ruim é que ele perderá o acesso à sua conta somente após três meses. Obviamente, para evitar isso, podemos solicitar que você altere sua senha todos os meses ou semanas. Mas pode ser irritante para os usuários finais.
Seria bom se não usarmos nossa senha com muita frequência em nossos pedidos. Para fazer isso, podemos introduzir um endpoint especial: http://api.mybank.com/login . Vamos enviar nossas credenciais apenas para esse terminal e, em troca, o servidor gerará para nós um token especial. Que seja apenas uma string única, GUID, que o servidor armazena em seu banco de dados. Vamos chamar essa string exclusiva de token de acesso. Nós o usaremos em vez de nosso nome de usuário e senha no cabeçalho de cada solicitação de conversa com o servidor. Semelhante à senha, vamos definir o tempo de expiração para o token de acesso.

Para atualizar o saldo, não precisamos de uma senha
Vamos reproduzir nosso experimento mental.
Estamos no ônibus e alguém roubou nossa solicitação de http para verificar o saldo. Mas agora a fraude tem apenas token de acesso.

Não é suficiente roubar apenas o token de acesso
O que hackers podem fazer agora com essas informações? Primeiro de tudo, ele ainda não pode gastar seu dinheiro. Segundo, ele não pode alterar a senha, simplesmente porque não a conhece. Além disso, agora o tempo de expiração da senha e do token de acesso são duas configurações separadas. Podemos deixar o tempo de expiração da senha em três meses e precisamos escolher a expiração do token de acesso. Gostaríamos de definir esse tempo o mais curto possível, porque, para obter um novo token de acesso, não podemos usar o próprio token. Se alguém roubar esse token, ele poderá renová-lo pelo tempo que desejar.
Quando o token de acesso expirar, para obter um novo, precisamos enviar novamente as credenciais do usuário. Se você estiver em um ônibus por 30 minutos e o tempo de expiração do token de acesso for 15 minutos, será necessário enviar sua senha pelo menos 2 vezes. Normalmente, queremos atualizar o token de acesso mais cedo, digamos a cada 10 minutos, caso contrário, o usuário pode perceber alguns atrasos para obter um novo token. Além disso, ele resolve o problema quando poucas solicitações ao mesmo tempo falham devido ao token expirado e precisamos repeti-las na ordem correta após a obtenção do novo token.
Agora os resultados estão melhores. A fraude tem acesso aos nossos dados apenas por 10 minutos, em vez de 3 meses. Mas ele ainda tem boas alterações para roubar nossa senha e podemos não perceber isso até que ele roube nosso dinheiro.
O problema agora é obter o token de acesso, ainda precisamos da senha. E se gerarmos mais uma string única. Um token especial usado apenas para obter o token de acesso.
Para isso, nosso terminal de logon deve aceitar nome de usuário e senha e retornar um novo token chamado Atualizar token. Que vamos armazenar em nosso aplicativo móvel. A atualização do token pode ter um prazo de validade mais longo, por exemplo, um mês.

Renovar fluxo para tokens de atualização e acesso
Toda vez que precisamos renovar o token de acesso, precisamos enviar apenas o token de atualização. Portanto, nossa senha será enviada ao servidor apenas uma vez em um mês ou cada vez mais raramente. Basicamente, só precisamos de senha para recuperar o primeiro token de atualização.
Ainda precisamos do token de acesso para executar solicitações para obter alguns dados do servidor. Então:
POST /login with username and password returns us refresh token
POST /renew with refresh token returns us access token
POST /balance with access token returns us actual balance
Vamos reproduzir nosso experimento novamente.
Estamos em um ônibus. Nosso aluno está verificando seu saldo.
Mas agora nosso aplicativo usa token de atualização armazenado em algum lugar de um arquivo no celular.
O aplicativo está enviando solicitações como:
POST /renew
GET /balance
GET /balance
GET /balance
POST /renew
GET /balance
GET /balance
GET /balance
Como antes, o hacker interceptou algumas solicitações com o token de acesso em um barramento.
Como o tempo de expiração do token de acesso é de 15 minutos e estamos atualizando os tokens a cada 10 minutos.
O hacker pode usar informações roubadas apenas por 10 minutos ou menos.
E se ele cruzasse uma das solicitações / renew e tivesse atualização e token de acesso? Teoricamente, ele pode usar o token de atualização por um mês para obter novos tokens de acesso e ainda assim conseguir roubar dinheiro.
Porém, se gerarmos novamente os dois tokens em todas as solicitações / renovações, o servidor armazenará apenas um token de atualização por vez. A cópia de fraude do token de atualização também se tornou inválida em 10 minutos e ele não pode usá-lo sem nos informar que o token está comprometido. Se ele tentar renovar o token, ele invalidará o nosso token e seremos forçados a entrar novamente.
Mais uma vantagem do token de atualização é que não precisamos armazenar a senha em um aplicativo ou navegador e armazenar apenas o último token de atualização.
O interessante é que o token de acesso pode não ser apenas uma sequência aleatória, mas pode conter algumas informações úteis. Por exemplo, pode ser o tempo de expiração, o ID do usuário e a função do usuário. Nesse caso, é chamado de token independente e o servidor não precisa de acesso ao banco de dados para validar o token e as permissões de usuário. Pode ser muito útil em microsserviços, pois pode aumentar o desempenho e diminuir o acoplamento entre microsserviços.
Está um pouco fora do tema do artigo, mas vale a pena mencionar o scope
.
E se solicitarmos / renovar o endpoint apenas para o token de acesso que pode ser usado exclusivamente para verificar o saldo?
Se o usuário quiser gastar algum dinheiro, ele deve receber outro segundo token diferente para isso? Podemos chamar esse parâmetro de 'escopo'.
Para que possamos pedir / renovar? Scope = [balance, news]. Se nosso hacker ainda armazena esse token, ele não pode usá-lo para gastar nosso dinheiro!
A ideia baseada em dois tokens oferece uma segurança melhor do que apenas uma senha ou um token por design. Ao contrário de escolher uma senha mais longa ou algoritmos de segurança mais fortes.
Esta foi a minha explicação para o conceito básico por trás dos tokens e como eles funcionam.
Em uma prática, existem algumas implementações diferentes desse conceito que podem ser facilmente pesquisadas no Google.
Pequena observação sobre a flexibilidade na escolha de um prazo de validade para a senha e os tokens.
O tempo de expiração típico pode ser:
Para a senha, é de 3 a 6 meses. É bom ter essa limitação. Como os bancos de dados podem ser roubados e o usuário pode reutilizar a mesma senha nos serviços.
Para o token de atualização, o tempo de expiração pode ser de uma semana ou mês. Para as pessoas que trabalham em um escritório com algum site, é útil ter esse tempo pelo menos mais que um fim de semana. Caso contrário, eles precisam digitar a senha toda segunda-feira.
O tempo de expiração do token de acesso pode variar de 10 a 60 minutos. Um tempo mais curto requer mais solicitações de renovação, mas um tempo maior pode oferecer mais chances de fraude.
Conclusão :
Precisamos usar a senha para obter um token de atualização de longa duração. Em seguida, envie o token de atualização para obter o token de acesso de curta duração. Em seguida, utilize o token de acesso para executar solicitações úteis.