Vamos preparar o ambiente!
Para executar este projeto, você deverá ter instalado o Node.js e as dependências do npm. Será necessário ter instalado o banco de dados Mongodb e suas configurações. Além disso, iremos fazer requisições na API com a plataforma Postman.
Após clonar o projeto, execute o comando abaixo:
$ npm install
API com Node.js e Express
A API segue o padrão MVC, com arquivos de configuração como .gitignore e .env. Pacotes utilizados: cors
, dotenv-safe
, express
, mongoose
e nodemon
.
Autenticação
Este projeto já possui rotas organizadas e integração com o banco de dados. O próximo passo agora é criar o processo de autenticação (conferia o fluxo de autenticação logo abaixo).
Segue as orientações
Fluxo autenticação
🚩 Criação de usuária
Uma usuária é criada e sua senha é armazenada como um hash (usando o bcrypt)
🚩 Login da usuária
Na request de login, no body da request são enviados os dados necessários para autenticação (email e senha, por exemplo)
🚩 Autenticação da usuária
A senha é verificada com a do banco, se for igual, um token é gerado como resposta à requisição. No front, esse token é armazenado
🚩 Autorização de visualização
Com o login realizado, a cada nova requisição o token é enviado no body da requisição permitindo a autorização de visualização
Criar rota para criação de users
-
Criar rota para criar user em userRoute.js
$ router.post('/', controller.create);
-
Criar model de users com id, nome, email e senha
-
Criar método no controller para criar users
-
Criar um user de teste via Postman
Criptografar senha dos users
-
Instalar bcrypt
$ npm install bcrypt
-
Fazer require do bcrypt no
usersController.js
$ const bcrypt = require('bcrypt');
-
Gerar hash com senha recebida no body da request
$ bcrypt.hashSync(request.body.senha, 10);
const createUser = async (req, res) => {
const hashedPassword = bcrypt.hashSync(req.body.password, 10)
req.body.password = hashedPassword
const newUser = new UserSchema(req.body)
try {
const savedUser = await newUser.save()
res.status(200).json({
message: "User adicionado com sucesso!",
savedUser
})
} catch (error) {
res.status(500).json({
message: error.message
})
}
}
- Criar novo user no banco com a senha hasherizada e o login (email) recebido no body da request
Criar rota de login
-
Criar rota de login em
userRoute.js
$ router.post('/login', controller.login);
-
Buscar user a partir do email recebido na request, e mostrar um erro 401 caso não encontre
$ userSchema.findOne({ email: req.body.email }, function(error, user) {...}
UserSchema.findOne({ email: req.body.email }, (error, user) => {
if(!user) {
return res.status(401).send({
message: "User não encontrado",
email: `${req.body.email}`
})
}
})
- Comparar senha de user encontra com a senha recebida via request, e mostrar um erro 401 caso seja diferente
$ bcrypt.compareSync(request.body.senha, userFound.senha);
const validPassword = bcrypt.compareSync(req.body.password, user.password)
if(!validPassword) {
return res.status(401).send({
message: "Login não autorizado"
})
}
-
Instalar "jsonwebtoken" via npm install e fazer require do pacote JWT
$ const jwt = require('jsonwebtoken');
-
Importar SECRET (passo abaixo) e gerar token JWT a partir do nome e secret e devolver na request
$ jwt.sign({ name: user.name }, SECRET);
const token = jwt.sign({ name: user.name }, SECRET)
- Enviar uma resposta para a requisição
res.status(200).send({
message: "Login autorizado",
token
})
Criar rota autenticada
-
Gerar chave pelo https://travistidwell.com/jsencrypt/demo/ e guardar a chave pública
-
Instalar dotenv-safe
$ npm install dotenv-safe
-
Criar arquivo .env.example e .env, ambos com chave chamada SECRET
$ SECRET=chave_rsa_aqui_sem_aspas
-
Carregar as variáveis de ambiente no projeto, no arquivo app.js
$ require('dotenv-safe').config();
-
Depois disso, vamos recriar a String de conexão do localhost, iremos proteger nosso http://localhost... criando uma variável de ambiente chamada MONGODB_URI, que ficará dentro do arquivo
.env
.
Dentro do arquivo .env
ficará:
SECRET=chave_rsa_aqui_sem_aspas
MONGODB_URI= "mongodb://localhost:27017/databaseName"
Na String de conexão no arquivo database.js, ficará:
//String de conexão
mongoose.connect(process.env.MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true
});
-
Criar variável contendo a SECRET em userController.js
$ const secret = process.env.SECRET
-
Criar método de autenticação em
getAll
-
Pegar o header de autorização e enviar uma mensagem de erro 401 quando vir vazio
$ const authHeader = request.get('authorization');
const getAll = async (req, res) => {
const authHeader = req.get('authorization')
const token = authHeader.split(' ')[1];
if (!token) {
return res.status(401).send("Erro no header")
}
UserSchema.find(function (err, users) {
if(err) {
res.status(500).send({ message: err.message })
}
res.status(200).send(users)
})
}
-
Passar bearer token no header de autenticação via Postman
$ Bearer TOKEN_JWT_AQUI
-
Verificar token JWT e enviar uma mensagem de erro 403 caso seja inválido
$ jwt.verify(token, SECRET, (error) => {...});
Antes de tudo, precisamos importar a biblioteca jwt no controller
$ const jwt = require('jsonwebtoken');
Agora sim, podemos aplicar o método verify e verificar se tudo está pegando corretamente.
jwt.verify(token, SECRET, function(erro) {
if (err) {
return res.status(403).send('Não autorizado');
}