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

Node.js

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

Luiz Duarte
Escrito por Luiz Duarte em 28/12/2020
Junte-se a mais de 22 mil profissionais de TI

Entre para minha lista e receba conteúdos exclusivos e com prioridade

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 MySQL, um popular banco de dados SQL.

Atenção: este é um tutorial intermediário. Parto do pressuposto aqui que você já conhece Node.js e MySQL 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 MySQL, conheça meu curso online (banner abaixo) e meu livro.

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 MySQL, substituindo o array do tutorial anterior.

Eu já expliquei tudo que você precisa saber sobre como configurar o ambiente MySQL 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 MySQL deles usando os créditos que você ganha quando se cadastra.

Voltando ao nosso projeto Node.js, instale o driver do MySQL 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 fullstack JS), 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, as abaixo:

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 vamos criar um módulo db.js, que vai fazer a gestão da conexão com o MYSQL. Crie-o na raiz do projeto.

Esta função apenas garante que teremos uma única conexão com o banco de dados sendo reaproveitada em toda aplicação. Existem técnicas bem mais avançadas que isso, como usar um ORM por exemplo. Note que exportei a função ao final, para que quando este módulo for carregado a primeira vez, possamos criar a conexão.

Agora modifique o seu bin/www (geramos este projeto com o express-generator, lembra?) para que importe o nosso db.js e chame o connect:

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 possuirá as funções de manipulação com o banco e mesmo que a gente carregue ele em outros pontos da aplicação, ele usará o que já está em cache. Também coloquei como primeira linha o carregamento das variáveis de ambiente. Caso o .env não exista, teremos um erro. Caso não consiga se conectar ao banco, teremos um erro (certifique-se criar um banco com o nome ‘passport’ no seu mysql, ou mude a connection string de acordo). 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 MySQL local ou remoto e crie no banco ‘passport’, a tabela ‘users’, conforme SQL abaixo:

Depois, adicione nela 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

#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 MySQL 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 express-mysql-session e adicione-o na chamada do session, para que ele passe a apontar para o MySQL 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 MySQL e que os dados de sessão devem ser apagados automaticamente após 30 minutos.

#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 para que usem nosso banco de dados. Vamos começar voltando ao nosso db.js e criando duas novas funções lá.

Agora, vamos abrir nosso auth.js, removendo o array de users, removendo as funções de findUser e findUserById originais e depois refatorando as duas chamadas das funções antigas para que usem as novas do objeto db, como abaixo.

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

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

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

Quer aprender a publicar esta aplicação na Amazon? Dê uma olhada neste tutorial!

Ou então publique na Umbler, que nem precisa de tutorial. 🙂

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

Olá, tudo bem?

O que você achou deste conteúdo? Conte nos comentários.