Consumindo API REST com autenticação JWT no React Native

Criando uma aplicação que realiza o consumo de uma API, com o tipo de autenticação JWT utilizando Interceptors do Axios e o AsyncStorage

Matheus Tadeu
React Brasil
Published in
9 min readDec 26, 2019

--

Créditos da Imagem https://bit.ly/2tKge8W

Muitas empresas atualmente, utilizam o conceito de API em seus sistemas para facilitar a troca de informações entre plataformas Web e aplicativos com as bases de dados, afim de conseguir isolar essa informação em um módulo, e poder utiliza-lá em qualquer aplicação que for construída, além de poder compartilhar essas informações de forma mais fácil, com parceiros no mercado.

Uma API é a forma mais usada de integrar sistemas, podemos pensar nelas como algo que liga aplicações, que necessitam de uma determinada informação, como por exemplo, o Login pelo Facebook, que está presente em vários aplicativos, porque existe uma API para empresas de terceiros utilizarem. Também quando você está fazendo, alguma compra na internet e após digitar seu CEP, seu endereço é automaticamente completado, isso acontece graças a uma API dos Correios, que tem o mapeamento da maioria dos endereços no Brasil, e está disponível nesse link para acesso.

Como elas começaram a ser utilizadas em grande escala no mercado, ao decorrer do tempo, algumas questões, de como construir esses serviços de forma prática, eficiente e segura, foram surgindo e com isso foram feitos alguns modelos, e arquiteturas para construir esse serviços, um deles é a autenticação de usuários a uma API utilizando um código de identificação, chamado Token JWT que é bastante usado pelo mercado.

O Token JWT mais conhecido como JSON Web Token que segundo sua documentação oficial disponível nesse link para acesso, é um método (RFC 7519) padrão da indústria, que define uma maneira compacta e independente de transmitir com segurança informações entre partes como um objeto JSON.

Agora como iremos usar essa técnica de Token JWT com uma API e meu aplicativo ?

Em uma API que está utilizando esse tipo de autenticação, geralmente na chamada de login, em que o usuário inicia uma sessão, a resposta dessa chamada vai ser semelhante a isso:

"user": {
"id": 1,
"email": "bruno@email.com"
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyU2VuZCI6eyJpZCI6MSwiZW1haWwiOiJicnVub0BlbWFpbC5jb20iLCJwYXNzd29yZCI6ImJydW5vIn0sImlhdCI6MTU3MzM2MjE4OSwiZXhwIjoxNTczMzYyNzg5fQ.wfHnMfeOTN9Dt28PcTiEf25t8foq_ky3i6wyMzZpnQU"

Onde o campo token, possui o Token JWT que é um código em Base64 e que vai ser usado, para acessar as rotas internas dessa API, que somente usuários autenticados podem acessar.

Funcionamento das Rotas em API REST com JWT

Para quem não conhece muito sobre API REST e o seu funcionamento recomendo um estudo desse tópico antes de avançarmos. Cada API possui suas rotas ou também os conhecidos end-points, que podem ser acessadas através de seu nome e URL do servidor em que está disponível, por exemplo:

http://pokeapi.co/api/v2/pokemon

Essa URL da PokeAPI quando acessada, nos devolve um JSON com o nome e o link para mais informações, de 20 Pokemons que estão cadastrados na base de dados dessa API.

Essa é uma rota pública, pois qualquer pessoa pode acessar, geralmente em API REST com JWT as rotas públicas, são a de início de sessão (Login) e cadastro de usuários.

E rotas que exibem informações, que somente os usuários daquela aplicação podem visualizar são as rotas privadas da API, e necessitam do envio do Token JWT pelos Headers da requisição.

Iniciando o aplicativo

Agora que já sabemos o conceito de uma API REST que utiliza JWT para autenticação, podemos seguir para a criação do aplicativo em React Native para isso podemos usar o react-native-cli assim vamos poder usar o react-native init para iniciarmos o projeto do zero.

react-native init app-api

Lembrando que esse será o link da API utilizada nesse tutorial

https://api-jwt-tutorial.herokuapp.com

É uma API bem simples, onde é possível realizar a autenticação com todos os usuários, que estão no arquivo users.json que está disponível, para acesso em seu código, que está nesse repositório e também existe a rota /products que necessita estar autenticado para acessar, e o seu retorno é uma lista com produtos.

Após isso, vamos instalar o Axios um pacote, que vamos usar para realizar as chamadas a API e que vai nos ajudar a manter o Token JWT nas rotas, que precisam de autenticação para serem acessadas.

yarn add axios// or npm i axios

Agora já estamos com o projeto totalmente configurado, e podemos rodar o mesmo, usando react-native run-android ou react-native run-ios

Aplicativo funcionando sem problemas

Agora que já temos tudo configurado e o Axios instalado, podemos começar fazendo a tela de Login do aplicativo, que vai se chamar Welcome, e está construída da seguinte forma:

Essa tela possui dois inputs um para o usuário digitar seu Email e outro a senha para acesso, e abaixo um botão com o texto Prosseguir, onde após seu clique o usuário, caso suas informações estiverem corretas será logado no aplicativo. Para gerenciar os valores dos campos de texto está sendo usado dois estados, um para gerenciar o carregamento da chamada da API do Login, e também um estado, que está sendo usado, para gerenciar as informações de erro que podem ocorrer, lembrando que esse componente está construído usando React Hooks e para criar valores de estado, é usado o Hook chamado useState, que nos permite ter valores no estado em componentes escritos em forma de função.

Quando o usuário clica no botão de login para realizar o acesso, a função signIn é chamada e é feito uma chamada a API passando um objeto chamado credentials que contém o Email e senha utilizados no login, e na resposta dessa requisição, como já foi mostrado é devolvido o Token JWT, que após isso é salvo no AsyncStorage, para ser utilizado depois pelo Axios.

Com isso finalizado, agora vamos fazer a tela responsável, por verificar caso existe um Token JWT salvo no armazenamento do aplicativo, e caso ele estiver salvo e for válido, o aplicativo já irá iniciar na Home, assim não sendo necessário o usuário fazer login para o acesso.

Essa sempre vai ser a primeira tela a ser exibida quando o aplicativo é iniciado, pois como já foi dito nela é feita a verificação caso existe Token, e com isso é decidido caso o usuário é redirecionado para a tela de Login ou para a página Home quando o token estiver salvo e válido.

Como já foi dito antes, para acesso as rotas privadas de uma API é necessário enviar o Token JWT, no nosso caso, as que são chamadas após a tela de Login são desse tipo, e é necessário enviar o Token JWT pelos Headers para ter acesso as informações. Mas como podemos sempre enviar o Token de forma automática, para todas essas requisições ?

Interceptors no Axios

Para facilitar o gerenciamento do Token JWT nesse cenário, existe bibliotecas como o Axios que possuem o conceito de Interceptors. Com seu uso é possível, que você intercepte as requisições ou respostas da API, tendo um funcionamento parecido com os middlewares em Back End, com isso antes mesmo do Axios devolver a resposta, ou fazer uma requisição, é possível fazer alterações nas configurações dessas operações.

Nesse caso como também já foi dito, vamos precisar adicionar um header com o nosso Token JWT dessa forma:

Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyU2VuZCI6eyJpZCI6MSwiZW1haWwiOiJicnVub0BlbWFpbC5jb20iLCJwYXNzd29yZCI6ImJydW5vIn0sImlhdCI6MTU3MzM2MjE4OSwiZXhwIjoxNTczMzYyNzg5fQ.wfHnMfeOTN9Dt28PcTiEf25t8foq_ky3i6wyMzZpnQU

Essa informação será adicionada no header de Authorization das nossas requisições, com a Flag Bearer, que é uma boa prática utilizada ao enviar um Token de autenticação para API JWT que possuem esse tipo de acesso.

Agora vamos adicionar o Token JWT no Header de nossas requisições, em um arquivo chamado api que será responsável, por realizar toda configuração das nossas requisições e respostas, incluindo o uso de Interceptors que vão incluir o Header.

Utilizando o Interceptor de response no Axios, é possível manipular todas as respostas de API incluindo as de sucesso ou erro.

api.interceptors.response.use(response => {   // Do something with response data   return response},error => {  // Do something with response error  // You can even test for a response code  // and try a new request before rejecting the promise  return Promise.reject(error)},)

Da mesma forma, é possível manipular a configuração de todas as requisições de API, ou também fazer algo caso ocorra um erro durante a requisição.

api.interceptors.request.use(  config => {    // Do something with config data  },  error => {    // Do something with request error
// You can do another request
return Promise.reject(error) },)

Agora voltando para o nosso cenário, no Interceptor de request foi alterado, o objeto de config, que contém todas as configurações da requisição, adicionando um novo Header de Authorization com o prefixo Bearer e o Token JWT, que foi obtido através de uma busca no AsyncStorage do React Native, onde o token foi salvo, na tela de Login do aplicativo.

Já no Interceptor de response caso ocorra um erro em uma resposta da API, é feita verificação, caso o Status Code for igual a 401 que é o código usado, quando o Token JWT é expirado após o seu tempo de uso, definido pela API que você estiver usando.

E caso realmente o código for 401 a função deleteUser é chamada, apagando o Token salvo no AsyncStorage, e redirecionando o usuário para a AuthLoadingScreen que vai verificar novamente, caso o Token existia e como ele foi deletado, o usuário irá para a tela de Login, e após a sua autenticação irá receber um novo Token JWT válido.

Lembrando que toda a navegação entre telas no aplicativo, foi feita usando a biblioteca React Navigation, e o arquivo de rotas ficou da seguinte forma:

import { createSwitchNavigator, createAppContainer } from 'react-navigation'import { createStackNavigator } from 'react-navigation-stack'import Welcome from './pages/Welcome'
import Home from './pages/Home'
import AuthLoadingScreen from './pages/AuthLoadingScreen'
const StackNavigator = createStackNavigator(
{
Home,
},
{
initialRouteName: 'Home',
}
);
const AuthStack = createStackNavigator(
{
SignIn: Welcome,
App: StackNavigator,
// SignUp: RegisterUser
},
{
initialRouteName: 'SignIn',
headerMode: 'none',
header: null,
},
);
const RootStack = createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
Auth: AuthStack,
App: StackNavigator,
},
{
initialRouteName: 'AuthLoading',
headerMode: 'none',
navigationOptions: {
header: null,
},
},
);
const RootStackContainer = createAppContainer(RootStack)export default RootStackContainer

Nele temos três esquemas de navegação no aplicativo, o primeiro deles é o StackNavigator, que é o grupo de telas, que somente podem ser acessadas após o login do usuário, o próximo é o AuthStack, que reune as telas usadas no fluxo de autenticação, nele está a tela de Login do aplicativo, que é chamada de Welcome, e uma rota chamada App que é o StackNavigator, com as telas que necessitam de autenticação, e por último o RootStack que é um SwitchNavigator, que para quem não conhece é o tipo de Navigator mais usado para fluxos de autenticação, pois ele não guarda nenhuma pilha de telas, ou seja caso o usuário clicar em voltar ele sai do aplicativo e não volta para nenhuma tela de autenticação, e nesse caso ele possui a AuthLoadingScreen, tela responsável por verificar caso existe o Token JWT salvo no AsyncStorage, também o AuthStack, reunindo as telas de autenticação, e a rota chamada App que possui o StackNavigator com as telas do aplicativo, que são visualizadas após o Login do usuário.

No AuthStack a tela SignUp está comentada, pois caso seu aplicativo também possua uma tela de cadastro de usuários, ela deveria ficar nesse grupo de telas.

Com isso só falta a tela Home do aplicativo, que é mostrada após o Login ser feito:

Na tela Home existe uma lista de produtos, que é obtida através de uma requisição na rota privada /products também existe um botão de Sair, que no seu clique, o Token JWT é deletado do AsyncStorage, e o usuário redirecionado para a tela de Login do aplicativo.

Com isso, chegamos ao fim do nosso aplicativo que consome uma API REST com autenticação JWT, utilizando boas práticas para o tratamento do Token no React Native 😃

Resultado final:

Resultado final 😃

O projeto está disponível nesse repositório no GitHub e qualquer dúvida que tiverem, ou se quiserem acrescentar algo, é só deixar um comentário.

Também não esqueça de me acompanhar nas redes sociais, para a gente trocar aquela ideia

matheustadeu.com

www.linkedin.com/in/matheus-tadeu/

Referências

--

--