Autenticação em Node.js com Passport e MongoDB

Recentemente escrevi um tutorial ensinando como utilizar o Passport, uma popular lib JavaScript para construção de middlewares de autenticação. Neste tutorial, fiz toda a gestão de sessão e de autenticação em memória, usando um array simples, para fins didáticos.

A gestão de sessão não é incomum ser feita em memória, mas possivelmente você irá querer a gestão dos seus usuários persistida em um banco de dados, certo?

No tutorial de hoje, vamos adaptar o projeto anterior (então baixe ele na sua máquina) para uso com MongoDB, um popular banco de dados NoSQL.

Atenção: este é um tutorial intermediário. Parto do pressuposto aqui que você já conhece Node.js e MongoDB em níveis básicos e também que já realizou o tutorial anterior, onde criamos este projeto com persistência em array.

Para ver a construção de uma aplicação web completa usando Node.js e MongoDB, conheça meu curso online e meu livro.

Curso FullStack
Curso FullStack

#1 – Configurando o banco de dados e variáveis de ambiente

Os dados de sessão dos usuários e os próprios usuários vão ficar armazenados em um banco MongoDB, substituindo o array do tutorial anterior.

Eu já expliquei tudo que você precisa saber sobre como configurar o ambiente MongoDB pra uso com Node neste tutorial e caso não esteja com tempo agora, sugiro apenas que crie uma conta na Umbler, crie um site Node.js e use o serviço de MongoDB deles usando os créditos que você ganha quando se cadastra. Outra opção é o MongoDB Atlas, que tem um plano gratuito.

Voltando ao nosso projeto Node.js, instale o driver do MongoDB para Node:

Note que instalei também o pacote dotenv-safe, que permitirá guardarmos variáveis de ambiente de uma maneira muito prática e profissional, permitindo fazer deploy do nosso projeto em produção sem ter de ficar trocando connection strings e coisas do tipo.

Para que o dotenv-safe funcione (ensino em videoaulas do meu curso de Node.js e MongoDB), você precisa criar dois arquivos novos: “.env” e “.env.example”. O “.env.example” é o template contendo quais variáveis de ambiente são obrigatórias para sua aplicação funcionar, em nosso caso, apenas três:

Já o “.env”, contém a sua versão local das variáveis e o ideal é que você inclua no seu .gitignore o .env, para que ele não seja commitado em produção (em produção você deve setar as variáveis de ambiente de produção, e não vai querer elas sobrescritas de maneira alguma):

Agora modifique o seu bin/www (geramos este projeto com o express-generator, lembra?) para que o servidor somente seja iniciado após a conexão com o banco de dados tiver sido realizada, como abaixo, onde uso a variável de ambiente como connection string:

Repare que eu encapsulei todo o conteúdo do bin/www em um IIFE. Isso foi necessário para conseguir usar async/await na conexão com o banco.

O objeto db é a conexão com o banco e vamos compartilhá-lo globalmente com os outros módulos que precisarem (apontando diretamente para o banco configurado na variável de ambiente). Caso o .env não exista, teremos um erro. Caso não consiga se conectar ao banco, teremos um erro. O projeto somente vai “subir” se estiver tudo 100%.

Se você rodar este projeto agora e tudo estiver 100%, você deve ver a mensagem no console de que a conexão foi bem sucedida.

Antes de prosseguirmos, é de bom tom cadastrarmos no mínimo um usuário em nosso banco de dados, para poder realizar os testes depois. Acesse o seu banco MongoDB local ou remoto e insira no banco passport, na coleção users, um usuário com os seguintes dados:

Coloque no campo email, um email seu de verdade, pois precisaremos dele funcionando mais tarde. Note que o password do usuário está criptografado em formato de hash Bcrypt. Esta senha na verdade é o hash da palavra “123”. 🙂

Curso Node.js e MongoDB
Curso Node.js e MongoDB

#2 – Refatorando o app.js

Antes de mais nada, no nosso app.js nós definimos um secret que é usado pelo Passport para criptografar algumas coisas dele. Hoje este secret está chumbado, mas vamos mudar isso para usar uma variável de ambiente, como abaixo.

Além disso, vamos instalar uma nova dependência no projeto para que o express-session use o MongoDB ao invés da memória para gerenciar as sessões. O express-session é muito extensível e basta instalarmos o conector para o banco de dados apropriado e fazer umas poucas configurações.

No app.js, no mesmo bloco de configuração do Passport, carregue o middleware de sessão do connect-mongo e adicione-o na chamada do session, para que ele passe a apontar para o MongoDB corretamente.

Aqui estou carregando nosso módulo auth.js passando o objeto passport pra ele configurar a estratégia de autenticação. Depois digo para o express-session usar a mesma string de conexão com o MongoDB e que os dados de sessão devem ser apagados automaticamente após 30 minutos, um recurso nativo do MongoDB chamando TTL Index.

#3 – Refatorando o auth.js

Agora que temos nosso banco rodando, vamos refatorar as partes do projeto que usavam o array em memória para fazer a gestão dos usuários, abrindo nosso auth.js e antes de tudo, removendo o array de users e depois refatorando as duas funções de findUser como abaixo.

Assim, ao invés de estarmos procurando em um array, estaremos procurando diretamente no banco de dados.

Como as funções do MongoDB são assíncronas, ou usamos callbacks, promises ou ainda async/await, que foi a opção que escolhi aqui. Devido a isso, temos de alterar as funções que chamam as findUser para que usem async/await:

e essa aqui também:

E com isso você tem novamente a sua aplicação web em Node.js funcionando e exigindo autenticação, mas agora com o MongoDB como persistência de dados!

Confira a parte 2 deste tutorial neste link.

Quer aprender a construir aplicações web usando Node.js e MongoDB com a mesma didática deste tutorial? Conheça o meu curso online ou meu livro.

Publicado por

Luiz Duarte

Pós-graduado em computação, professor, empreendedor, autor, Agile Coach e programador nas horas vagas.