Iniciando com AdonisJS: Autenticação JWT e API REST

Aqui na Rocketseat nós sempre estamos estudando e testando as tecnologias que estão crescendo no mercado de desenvolvimento e pra gente uma stack que está funcionando muito bem e integramos em praticamente todos projetos nossos é o NodeJS para back-end, ReactJSpara front-end web e React Native para mobile.

Já que pra gente está funcionando tão bem, resolvemos fazer uma série de posts criando uma aplicação do zero utilizando essas três ferramentas. No lado do back-end também utilizaremos o AdonisJS que é um frameworkaltamente robusto que nos permitirá agilizar muito o desenvolvimento do nosso app.

Mas que app é esse? Bom, já que não vamos conseguir fazer uma aplicação gigante aqui pelo blog iremos abordar os principais recursos que são importantes para você criar seu próprio app criando um clone do AirBnBcom recursos como:

  • Autenticação via JWT;
  • Cadastro de imóveis para aluguel;
  • Mapa com imóveis próximos (utilizando GPS);
  • Upload de fotos dos imóveis (utilizando a câmera no mobile);
  • e muitos mais…

Nessa primeira parte da série iremos criar nossa API REST com o AdonisJS para depois consumirmos no ReactJS e React Native. Fica tranquilo, caso queira pular esse passo vou deixar todo código disponível no Github mas seria muito legal você criar tudo isso do zero.

Ah, se você ainda não manja muito de Javascript e ES6, lembra que temos cursos gratuitos te esperando em nosso site.

Iniciando com AdonisJS

O AdonisJS é um framework para NodeJS que vai nos permitir focar na regra de negócio da nossa aplicação sem perder muito tempo com o funcionamento por trás de funcionalidades comuns como manipulação do banco de dados, envio de e-mail, autenticação, etc…

Para começarmos o desenvolvimento da nossa aplicação, vamos instalar o CLI (Command Line Interface) do Adonis que vai nos ajudar muito durante o desenvolvimento:

npm i -g @adonisjs/cli

Em uma pasta de sua escolha execute agora o seguinte comando que irá criar um novo projeto com a estrutura do Adonis:

adonis new airbnb-server --api-only

O airbnb-server é o nome que dei ao meu projeto, mas você pode dar o nome que preferir. O parâmetro --api-only no fim significa que não queremos a parte de views do Adonis já que vamos servir os dados do nosso app via REST para o ReactJS e o React Native.

Agora abra a pasta do projeto recém-criado e rode o comando adonis serve --dev. Esse comando basicamente iniciará nosso servidor de desenvolvimento que agora pode ser acessado no endereço http://localhost:3333.

Ah, uma parte bem legal do Adonis é que se você alterar qualquer arquivo esse servidor se auto reinicia com as novas alterações (graças ao Nodemon).

Abra o código no seu editor de preferência porque agora iremos pôr a mão na massa!!

Criando API REST com AdonisJS

A primeira coisa que precisamos entender é que o AdonisJS utiliza o padrão MVC como arquitetura, por isso veremos muito sobre models e controllers daqui pra frente.

Outro ponto muito importante é que toda camada de banco de dados é abstraída pelo Lucid ORM, isso quer dizer que jamais escreveremos uma consulta no banco de dados como SELECT * FROM users WHERE id = 1, ao invés disso utilizaremos métodos disponíveis nos nossos models, como: const user = User.find(1);

Para iniciar nosso app precisamos de um banco de dados SQL disponível, eu vou utilizar o PostgreSQL mas fique à vontade para utilizar MySQL ou até SQLite.

Rode o comando abaixo dependendo do banco que escolher:

  • MySQL: npm install mysql
  • PostgreSQL: npm install pg
  • SQLite: npm install sqlite3

Com isso feito, vamos configurar os acessos ao banco de dados através do arquivo .env que define nossas variáveis ambiente, ou seja, dados que podem variar de acordo com o ambiente da nossa aplicação: desenvolvimento, produção, staging, testes, etc…

Dentro do arquivo .env altere as seguintes linhas para os dados de acesso à sua base dados (lembre de alterar o DB_CONNECTION para o tipo de base que você está usando):

DB_CONNECTION=sqlite
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=root
DB_PASSWORD=
DB_DATABASE=adonis

Se tudo estiver correto você agora poderá executar o comandoadonis migration:run na raiz do seu projeto e obterá um resultado semelhante à:

migrate: 1503250034279_user.js
migrate: 1503250034280_token.js
Database migrated successfully in 262 ms

Basicamente o que aconteceu aqui foi que executamos todas migrations do nosso projeto em nossa nova base, mas o que são migrations? Pense nelas como um controle de versão da nossa base. Com elas podemos facilmente criar novas tabelas, alterar colunas e todos os outros desenvolvedores do projeto sempre terão a base de dados atualizada com o código.

Autenticação com JWT

Agora que nossa base de dados já tem espaço para cadastramos novos usuários vamos criar as rotas que farão esse processo. Ah, uma coisa bem legal, como mencionei antes, se você abrir o arquivo app/Models/User.js não verá nenhum campo da base de dados referenciado na classe, isso porque tudo isso é abstraído pelo Lucid e ele identifica os campos para a gente automagicamente 🙂

Para iniciar o processo de autenticação vamos criar nosso controller de usuários, para isso, em seu terminal execute o comando:

adonis make:controller User --type http

Nesse momento um novo arquivo app/Controllers/Http/UserController.js deve ter sido criado e dentro dele faremos nossas primeiras ações para cadastro e login de usuários. Começando com o cadastro, altere o conteúdo desse arquivo para:

"use strict"

const User = use("App/Models/User")

class UserController {
  async create ({ request }) {
    const data = request.only(["username", "email", "password"])

    const user = await User.create(data)

    return user
  }
}

module.exports = UserController

Basicamente o que estamos fazendo aqui em cada linha é:

  • Linha 3: Importamos o model de usuário;
  • Linha 6: Definimos um novo método assíncrono create que recebe um parâmetro request que possui todos dados da requisição como parâmetros, corpo, headers, etc. Veja que estamos utilizando {} por volta dos parâmetros, isso porque no AdonisJS utilizamos a desestruturação do ES6 no controller;
  • Linha 7: Buscamos os campos de username, email e password do corpo da nossa requisição e os armazenamos em um objeto chamado data;
  • Linha 9: Criamos um novo usuário repassando os parâmetros vindos da requisição e salvamos esse novo usuário em uma variável user;
  • Linha 11: Retornamos o novo usuário como resultado da requisição, como selecionamos, no nosso caso o retorno será um JSON.

Agora com o controller criado, vamos criar nossa rota que dará acesso a esse método, para isso no arquivo start/routes.js troque seu conteúdo para:

'use strict'

const Route = use('Route')

Route.post('/users', 'UserController.create')

Pronto, acabamos de criar uma rota que aceita o método POST no endereço /users e chama o método create no controller UserController, simples assim 🙂

Legal, mas como testamos isso? Eu gosto de utilizar o Insomnia que é um cliente para testar API’s REST, você pode baixá-lo para prosseguir.

Dentro do Insomnia clique na ação “New request” para criar uma nova requisição, nomeie a mesma como “Cadastro” e com ação POST e no tipo de corpo da requisição selecione JSON. No topo preencha com o endereçopara a rota que acabamos de criar e adicione alguns dados ao corpo em formato JSON para criarmos o primeiro usuário:

Agora, clique no botão “Send” para realizar a requisição e você deve obter um resultado como o seguinte:

Booooooa!!! Acabamos de criar nosso usuário, veja que legal, o AdonisJS inclusive já criptografou a senha do usuário automaticamente (essa lógica está dentro do model de usuário, falaremos mais sobre isso depois).

Agora que temos nosso querido usuário cadastrado vamos fazer a lógica de autenticação, por isso, como uma boa prática vou criar um novo controller para lidar apenas com a autenticação (sessão), para isso, execute o comando adonis make:controller Session --type http.

Dentro desse arquivo adicione o seguinte código:

'use strict'

class SessionController {
  async create ({ request, auth }) { 
    const { email, password } = request.all()

    const token = await auth.attempt(email, password)

    return token
  }
}

module.exports = SessionController

Veja que dessa vez, além de buscar a request buscamos também uma variável auth dos parâmetros que é o meio que o Adonis nos dá para realizarmos a autenticação de forma simples.

Resgatamos os campos de e-mail e senha da requisição e executamos o método auth.attempt para fazer login e retornar nosso token JWT (já falaremos sobre ele).

Antes de prosseguir, vamos agora criar nossa rota de autenticação sobrescrevendo o conteúdo do arquivo start/routes.js por:

'use strict'

const Route = use('Route')

Route.post('/users', 'UserController.create')
Route.post('/sessions', 'SessionController.create')

Agora no Insomnia crie uma nova requisição com a nova rota passando o e-mail e senha do usuário recém-criado para testar tudo isso:

Enviando essa requisição agora teremos acesso ao token JWT que servirá para validarmos se o usuário está autenticado ou não em nosso app.

Pronto!!! Nossa API já está mais do que pronta para partirmos para os próximos passos como criação de imóveis, upload de imagens e retorno de imóveis próximos baseados na latitude e longitude do usuário, mas isso é assunto para o próximo post da série.

Com esse token que recebemos no login vamos conseguir validar nas requisições que precisam de autenticação, como um cadastro de imóvel, se o usuário é válido e está autenticado em nossa aplicação.

O fim de uma etapa

Por esse post vamos ficar por aqui, criamos toda nossa API com AdonisJS do total zero realizando cadastro e autenticação via JWT e salvando nossos dados no banco.

Aprendemos também alguns conceitos importantes como o ORM, models, controllers, migrations, JWT, etc…

Lembrando que nos próximos posts dessa série vamos muito mais a fundo criando o restante da nossa API REST e consumindo esses dados através de uma aplicação front-end web com ReactJS e mobile com React Native.

Código produzido nesse post: https://github.com/rocketseat/blog-adonis-reactjs-react-native-airbnb/tree/auth

Não esquece de deixar seu comentário aí em baixo pra eu saber que você está gostando dessa série!