Solução

Usar um padrão de token já conhecido e que passou pela prova de tempo, como o JWT, é uma boa ideia. Porém, usar padrões conhecidos não “garante” segurança coisa nenhuma. É uma armadilha da mente acreditar que é realmente possível garantir que algo é “seguro”. É literalmente impossível garantir isso.

Mesmo que supostamente não haja nenhum erro no padrão do JWT, ou erro na biblioteca usada para a implementação do JWT, ainda sim pode haver outros erros no processo de autenticação.

Nesse exercício temos dois tokens:

  1. auth: Que é o token de autenticação normal;
  2. refresh: Que é o token de refresh usado para obter um novo token de autenticação e um novo token de refresh.

Bem, se ao fazer o refresh do token obtemos um novo token auth e um novo token refresh, então um atacante que conseguir um token de refresh do usuário poderá manter acesso à conta dele virtualmente para sempre.

Pois esse token nunca é invalidado e se o atacante ficar fazendo novos refreshs antes do token atual expirar, ele manterá o acesso à conta do usuário por quanto tempo quiser.

Note que ao atualizar a senha do usuário, o token de refresh não é invalidado. Ou seja, ele é válido enquanto o JWT não expirar.

Para fazer esse processo de autenticação, seria importante que o token refresh não fosse um JWT mas sim um token armazenado em banco de dados e que possa ser excluído/invalidado quando o usuário quiser ou quando o usuário alterar a senha da conta dele.

E o token auth é importante que tenha um tempo de expiração baixo, como 1 minuto, para quando o token refresh for invalidado aquele token auth não durar muito tempo como um token válido.