Começando uma API REST com Node.JS #3
Tags: braziliandevs, node, tutorial, api
Published: 2022-08-12 20:45:27

Nossa API já está acessando o banco de dados mongo e agora vamos implementar autenticação JWT para adicionarmos um passo de segurança.

Esse tipo de autenticação é muito comum e é usada para que apenas pessoas autorizadas acessem nossos métodos da API.

## O que é o JWT? (JSON Web Tokens)
JWT é uma string codificada que será usada como chave para concluir uma requisição à nossa API.

Toda requisição feita para nossa API o token será validado, permitindo ou não que a transação seja concluída com sucesso.

Esse token é formado por alguns dados criptografados e uma chave privada, que será usada para validar.

Não é indicado que se salve dados sensíveis nesse token, por mais que ele seja criptografado, é possível reverter essa criptografia e assim ler os dados ali contidos.

Leia mais sobre JWT [aqui](https://jwt.io/).

## Implementando autenticação JWT
Como nossos usuários não têm senha no banco, vamos começar por isso e adicionar uma senha para eles.
Para facilitar, essa é a senha 123456 criptografada: `16fd10090c85fadf1e2413980214b135fafa0169ded1939004ecc4e17dc31b77`
Vamos dar um update em nossos usuários e adicionar o campo **senha**.

Não se esqueçam de atualizar a model de usuário com esse novo campo!

Também alteramos o método de criar usuário, para criar com a senha criptografada:
```
const crypto = require('crypto');
const secret = 'minhastringdeseguranca101010';
 
exports.post = async (req, res, next) => {
   const hash = crypto.createHmac('sha256', secret)
       .update(req.body.senha)
       .digest('hex');
   const usuario = await UsuarioModel.create({
       ...req.body,
       senha: hash
   });
   res.status(200).send(usuario);
};
```
```
npm install jsonwebtoken
```
Criaremos uma pasta em _src_, chamada Middleware, e dentro dela um arquivo _Auth.js_
```
const jwt = require('jsonwebtoken');
const secret = 'minhastringdeseguranca101010';
 
exports.auth = (req, res, next) => {
 const token = req.headers['authorization'];
 if (!token) return res.status(401).send({ auth: false, message: 'Essa rota requer autenticação.' });
  jwt.verify(token, secret, function(err, decoded) {
   if (err) return res.status(500).send({ auth: false, message: 'Token não autorizado.' });
  
   req.currentUser = decoded.userId;
   next();
 });
}
```
Nesse método, vamos pegar o valor de _authorization_ do header e validar ele com a biblioteca do JWT.

Criamos também um controller para fazer o login, AuthController.js

Notem que estamos utilizando uma lib chamada _crypto_, ela vem junto com o node, não precisa de instalação.
```
const UsuarioModel = require('../Models/Usuario');
const crypto = require('crypto');
const jwt = require('jsonwebtoken');
const secret = 'minhastringdeseguranca101010';
 
exports.login = async (req, res, next) => {
   const { senha, nome } = req.body;
   const hash = crypto.createHmac('sha256', secret)
       .update(senha)
       .digest('hex');
  
   const usuario = await UsuarioModel.findOne({ nome, senha: hash });
   if (usuario) {
       const token = jwt.sign({ userId: usuario._id }, secret);
       res.send({auth: true, token})
   } else {
       res.status(401).send({ auth: false, error: 'Nome ou senha inválidos.' })
   }
};
```
Adicionamos uma rota para o login: AuthRoute.js
```
const AuthController = require('../Controllers/AuthController');
 
module.exports = (app) => {
   app.post('/login', AuthController.login);
}
```
E puxamos ela no Routes/index.js
```
const UsuarioRoute = require('./UsuarioRoute');
const AuthRoute = require('./AuthRoute');
 
module.exports = (app) => {
   UsuarioRoute(app);
   AuthRoute(app);
}
```
Precisamos alterar nosso arquivo de rotas do usuário para adicionar o middleware que criamos logo acima:
```
const UsuarioController = require('../Controllers/UsuarioController');
const auth = require('../Middleware/Auth').auth;
 
module.exports = (app) => {
   app.post('/usuario', auth, UsuarioController.post);
   app.put('/usuario/:id', auth, UsuarioController.put);
   app.delete('/usuario/:id', auth, UsuarioController.delete);
   app.get('/usuarios', auth, UsuarioController.get);
   app.get('/usuario/:id', auth, UsuarioController.getById);
}
```
Pronto! Bem simples, não? Vamos testar!

Se tentarmos acessar nossa rota de get /usuarios vamos receber a seguinte mensagem:
![Resposta do GET sem autenticação](https://lh6.googleusercontent.com/8l98C3qFAUjtQtqVxVBmS92m6IiNgT-RT5VSKdRDZdqRBo9JXeyd_MDOsgrgE-ph-7kRBf7wO-lasOYijqSUI24vTAjYxolM3LraP5kRA271hmnhH2MiwtuYuerWUg_6RCi8iGI)
Muito bom! Agora vamos fazer o login: O usuário que temos é “Mariana” e a senha “123456”.
![Resposta do GET com autenticação](https://lh3.googleusercontent.com/D7e5UNiLdj1hSJxhCktIC7gpE0gYOY1eYJn2Y6-XRebS-Y3AkLKudxQGxiAZVvdwwIH3SGDTISoRWw-Gi1O822vXc_LwPEaPZMY35pKv41dX15VqzijlwUrMFZOijPAviUSMMKg)
Veja que retornou o token, é isso que vamos usar para fazer as próximas requisições agora.

Voltando pra requisição em usuários, vamos adicionar um parâmetro no header: Authorization, com o valor do token que recebemos quando fizemos o login.
![JSON de retorno](https://lh4.googleusercontent.com/92_WwVeLEO72L7qlf_4RlyN1G3IssEfjtXB7WbAOi1vsVnA9G9E2LSd4V_rwmQLoSQCx44ApdYpv4GQY8IdPtXU9xaMXFnd8hy2bdUDjOKdEaKLRk0QyCBr04-9LEvUwSdrlVMM)
Veja que agora ele retorna os dados, completando a requisição.

E assim implementamos com sucesso um esquema de autenticação em nossa API!

*Para uma melhor segurança, o ideal é usar um arquivo .env para salvar o valor da nossa variável _secret_

Até um próximo artigo 🙂

---