ASP.NET Core 2.0 + JWT: implementando Refresh Tokens
Já abordei em artigos anteriores a utilização de JSON Web Tokens (JWT) em APIs REST construídas com o ASP.NET Core 2.0. Empregando tokens criptografados, esta técnica é suportada pelas principais plataformas de desenvolvimento da atualidade e oferece um meio seguro para o acesso a recursos de uso restrito.
O fato de um token possuir um tempo de validade pré-determinado pode ser uma limitação em algumas situações. Expirado tal token um novo deverá ser gerado, a fim de permitir que se continue a interação com os recursos providos por uma API.
Soluções para contornar este comportamento existem e envolvem o uso de Refresh Tokens:
- Um valor adicional (um segundo token) será gerado, a fim de permitir a solicitação posterior de um novo token de acesso atualizado;
- Este procedimento dispensa a necessidade de se repetir todo o processo de autenticação que aconteceu durante a obtenção do token inicial, contribuindo assim para uma maior performance.
Discuti em detalhes o uso de JWT com ASP.NET Core no seguinte artigo:
ASP.NET Core 2.0: autenticação em APIs utilizando JWT (JSON Web Tokens)
Este novo post complementa a solução apresentada no artigo mencionado, através das modificações descritas a seguir.
E aproveito este espaço para deixar aqui um convite.
Dia 07/05/2018 (segunda-feira) às 22h00 — horário de Brasília — teremos mais um hangout no Canal .NET,. Neste Live Demo demonstrarei como implementar testes de aplicações Web utilizando o .NET Core e o Selenium WebDriver. A transmissão acontecerá via YouTube em um link a ser disponibilizado em breve.
Para efetuar a sua inscrição acesse a página do evento no Facebook ou então o Meetup. A transmissão acontecerá via YouTube, em um link a ser divulgado em breve.
Implementando o uso de Refresh Tokens
Foram adicionadas ao projeto APIAlturas as classes:
- AccessCredentials, que pode conter as credenciais de acesso (usuario + chave) ou o Refresh Token;. Será a propriedade GrantType que identificará o conjunto de dados que se está manipulando (valores password ou refresh_token);
- RefreshTokenData, representação com os dados necessários para a inclusão de um Refresh Token um meio de armazenamento temporário (para isto será utilizado o Redis).
Na classe Startup serão incluídas instruções no método ConfigureServices para ativar o uso de cache via Redis. O armazenamento temporário de um Refresh Token procura restringir sua utilização por um tempo pré-estabelecido, evitando assim potenciais falhas na segurança da aplicação:
O tipo LoginController também passou por alterações:
- Os dados enviados no corpo de uma requisição correspondem às informações da classe AccessCredentials;
- Uma instância de IDistributedCache será recebida via injeção de dependência (foi marcada com o atributo [FromServices]), a fim de possibilitar a interação com o Redis e o armazenamento temporário de Refresh Tokens (o tempo em que um token deste tipo permanecerá armazenado está indicado na propriedade FinalExpiration de TokenConfigurations);
- A autenticação convencional (usuário + chave) ou via Refresh Token será verificada através da propriedade GrantType definida em AccessCredentials. Em se tratando de um Refresh Token, o mesmo será removido (um novo token deste tipo será gerado, assim como outro para acesso à API de alturas via Bearer Authentication);
- O código referente à geração do token para acesso à API de alturas (e que contém informações adicionais, como o Refresh Token) foi transferido para o método GenerateToken.
Os fontes do projeto descrito neste artigo já estão disponíveis no GitHub:
https://github.com/renatogroffe/ASPNETCore2_JWT-RefreshTokens
Testes
Um primeiro teste via Postman trouxe o Access Token (utilizado no header de requisições para autenticação) e o Refresh Token:
Neste momento será possível observar que o Refresh Token já se encontra armazenado no Redis:
Na próxima imagem está o resultado retornado pela API de conversão de alturas, com a requisição em questão tendo sido configurada para o uso do Access Token via Bearer Authentication:
Um novo token de acesso pode também ser obtido através do uso do Refresh Token (desde que esse último esteja dentro do período de validade):
E para concluir este artigo não deixe de acompanhar também o post a seguir, em que venho agrupando todos os conteúdos que tenho produzido sobre o uso de JWT em ASP.NET Core: