Desenvolvendo um login com NodeJS, MongoDB, Express e Passport.
Tags: braziliandevs, javascript, database, tutorial
Published: 2024-01-23 17:06:27

#Introdução
Este artigo explora a utilização do Express.js, um framework que simplifica a estruturação de aplicações web por meio de middleware e rotas. Além disso, aborda o MongoDB, um banco de dados NoSQL popular que oferece uma abordagem distinta para o armazenamento de dado

[Express.js](https://expressjs.com/pt-br/) é um framework que simplifica a organização de funcionalidades em aplicações, facilitando o uso de middleware e a definição de rotas.

[MongoDB](https://www.mongodb.com/docs/) é um banco de dados NoSQL popular. Ao contrário dos bancos relacionais, como tabelas, o MongoDB oferece uma abordagem diferente para armazenar dados, utilizando o formato chamado BSON.

[Passport.js](https://www.passportjs.org/docs/)é um middleware de autenticação flexível para NodeJS. Ele pode ser facilmente integrado em qualquer aplicação web baseada em Express, tornando a implementação de autenticação mais simples e personalizável.

#Passos para criar o projeto e instalar os modulos:
Vamos iniciar um novo projeto usando 
```
npm init
```

Instale os modulos usando o comando

```
npm i express ejs mongoose body-parser express-session
npm i passport passport-local 
npm i passport-local-mongoose 
```
Crie duas pastas dentro do diretorio do projeto usando o comando

```
mkdir model
mkdir views
```

Crie um arquivo `app.js`
Dentro da pasta model, crie um arquivo `User.js` o que vai ter os nossos [Schemas](https://www.devmedia.com.br/banco-de-dados-nosql-um-novo-paradigma-revista-sql-magazine-102/25918)
Dentro da pasta views crie os seguintes arquivos

```
home.ejs
login.ejs
secret.ejs
register.ejs
```
[EJS](https://ejs.co) é uma linguagem de modelo que permite incorporar codigo JS diretamente em um arquivo de modelo.

Estrutura do projeto deve se parecer com algo assim

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pw0zfkd7ke83gj5nhlqc.png)

Dependencias no package.json
```json
"dependencies": {
    "body-parser": "^1.20.2",
    "ejs": "^3.1.9",
    "express": "^4.18.2",
    "express-session": "^1.17.3",
    "mongoose": "^8.1.0",
    "passport": "^0.7.0",
    "passport-local": "^1.0.0",
    "passport-local-mongoose": "^8.0.0"
  }
```

No User.js vamos definir um schema que recebe dois campos `username`e `password`, o `passportLocalMongoose`adiciona os metodos e campos adicionais ao schema pra facilitar a autenticação local. 

```js
//Arquivo User.js
const { default: mongoose } = require('mongoose')
const mangoose = require('mongoose')
const Schema = mongoose.Schema 

const passportLocalMongoose = require('passport-local-mongoose')

const User = new Schema({
    username: {
        type: String
    },
    password: {
        type: String
    }
})

User.plugin(passportLocalMongoose)

module.exports = mongoose.model('User', User)
```

No arquivo app.js vamos começar definindo as libs do projeto

```js
//Arquivo app.js

const express = require("express"),
    mongoose = require("mongoose"),
    passport = require("passport"),
    bodyParser = require("body-parser"),
    LocalStrategy = require("passport-local"),
    passportLocalMongoose = 
        require("passport-local-mongoose")
const User = require("./model/User")
let app = express()
```
Vamos criar uma conexão com o MongoDB

```js
mongoose.connect("mongodb://localhost/27017")
```
Vamos configurar o express para usar a engine de visualização do EJS, configurar o middleware para processar os dados do formulário e a autenticação com Passport.js

```js

app.set('view engine', 'ejs')
app.use(bodyParser.urlencoded({ extended: true}))
app.use(require("express-session")({
    secret: "xxx",
    resave: false,
    saveUninitialized: false
}))

app.use(passport.initialize())
app.use(passport.session())

passport.use(new LocalStrategy(User.authenticate()))
passport.serializeUser(User.serializeUser())
passport.deserializeUser(User.deserializeUser())

```
Agora vamos configurar as rotas GET com express.
```js
app.get('/', (req,res)=>{
    res.render('home')
})


app.get('/secret', isLoggedIn, (req,res)=>{
    res.render('register')
})

app.get('/register', (req,res)=>{
    res.render('register')
})


app.get('/login', (req,res) =>{
  res.render('login')
})

```
Vamos definir a rota que vai tratar as solicitações post para o endpoint `/register`, que cria um novo usuario com base no dados fornecidos no formulario do `register.ejs`. 

```js
app.post('/register', async (req,res)=>{
    const user = await User.create({
        username: req.body.username,
        password: req.body.password,
    })
    return res.status(200).json(user)
})
```
Agora definir a rota de login que lida com autenticação dos usuarios e logout que, bom, faz log out

```js
app.post('/login', passport.authenticate('local', {
  sucessRedirect: '/secret',
  failureRedirect: 'login',
 // failureFlash: true,
}))

app.get("/logout", (req, res)=> {
    req.logout((err)=> {
        if (err) { return next(err) }
        res.redirect('/')
      })
})
```
Vamos criar uma função que age como middleware que vai garantir que só usuários autenticados tenham acesso a rotas privadas da aplicação.
```js
function isLoggedIn(req,res,next){
    if(req.isAuthenticated()) return next()
    res.redirect('/login')
}
```
Por fim vamos definir a porta para acessar-mos e fazer os testes localmente e por o servidor online.

```js
const port = 3000 
app.listen(port, ()=>{
    console.log('🔥')
})
```
Pra tudo acima funcionar você precisa ter o um servidor mongoose rodando. Caso não tenha eu escrevi um artigo sobre como preparar o ambiente [Preparando ambiente de trabalho MongoDB](https://dev.to/starch1/preparando-ambiente-de-trabalho-para-usar-mongodb-45mf)

Você pode iniciar o servidor com o comando 
```shell
mongod
```
Depois navegue até a pasta onde está o app.js e digite no terminal
```shell
node app.js
```
Abra o navegador e digite na barra o endereço:
```
http://localhost:3000/
```

#Conclusão
Integrando essas tecnologias, você ganha não apenas eficiência no desenvolvimento, mas também uma base sólida para construir aplicações escaláveis e seguras. O uso intuitivo de middleware, a flexibilidade do MongoDB e a robustez da autenticação com Passport.js proporcionam uma experiência de desenvolvimento acessível, mesmo para aqueles que estão começando.