es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo utilizar Mongoose/Mongodb con node.js – autenticación de passport.

Estoy construyendo mi primera aplicación de pila completa node.js y quiero usar passport para la autenticación. Encontré un tutorial para passport que almacenaba la información de los usuarios en una matriz de usuarios.

Archivo passport-config.js:

const LocalStrategy = require('passport-local').Strategy
const bcrypt = require('bcrypt')

function initialize(passport, getUserByEmail, getUserById) {
  const authenticateUser = async (email, password, done) => {
    const user = getUserByEmail(email)
    if (user == null) {
      return done(null, false, { message: 'No hay ningún usuario con ese correo electrónico' })
    }

try {
  if (await bcrypt.compare(password, user.password)) {
    return done(null, user)
  } else {
    return done(null, false, { message: 'Contraseña incorrecta' })
  }
} catch (e) {
  return done(e)
}
}

passport.use(new LocalStrategy({ usernameField: 'email' }, authenticateUser))
  passport.serializeUser((user, done) => done(null, user.id))
  passport.deserializeUser((id, done) => {
    return done(null, getUserById(id))
  })
}

module.exports = initialize

Archivo server.js

if (process.env.NODE_ENV !== ‘production’) {
require(‘dotenv’).config()
}

const express = require(‘express’)
const app = express()
const bcrypt = require(‘bcrypt’)
const passport = require(‘passport’)
const flash = require(‘express-flash’)
const session = require(‘express-session’)
const methodOverride = require(‘method-override’)

const initializePassport = require(‘./passport-config’)
initializePassport(
passport,
email => users.find(user => user.email === email),
id => users.find(user => user.id === id)
)

const users = []

app.set(‘view-engine’, ‘ejs’)
app.use(express.urlencoded({ extended: false }))
app.use(flash())
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
app.use(methodOverride(‘method’))

app.get(‘/’, checkAuthenticated, (req, res) => {
res.render(‘index.ejs’, { name: req.user.name })
})

app.get(‘/login’, checkNotAuthenticated, (req, res) => {
res.render(‘login.ejs’)
})

app.post(‘/login’, checkNotAuthenticated, passport.authenticate(‘local’, {
successRedirect: ‘/’,
failureRedirect: ‘/login’,
failureFlash: true
}))

app.get(‘/register’, checkNotAuthenticated, (req, res) => {
res.render(‘register.ejs’)
})

app.post(‘/register’, checkNotAuthenticated, async (req, res) => {
try {
const hashedPassword = await bcrypt.hash(req.body.password, 10)

const users = new User({
name: req.body.name,
email: req.body.email,
password: hashedPassword

})
await users.save()
res.redirect(‘/login’)

}

catch(err){
console.log(err)
res.redirect(‘/register’) }
})

app.delete(‘/logout’, (req, res) => {
req.logOut()
res.redirect(‘/login’)
})

function checkAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next()
}

res.redirect(‘/login’)
}

function checkNotAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return res.redirect(‘/’)
}
next()
}

app.listen(3000)


Estoy utilizando una base de datos mongoDb para mi aplicación y quiero almacenar los usuarios en mi base de datos. He realizado los cambios necesarios en la ruta de registro y puedo almacenar los datos en mi base de datos con éxito.

app.post(‘/register’, checkNotAuthenticated, async (req, res) => {
try {
const hashedPassword = await bcrypt.hash(req.body.password, 10)

const users = new User({
name: req.body.name,
email: req.body.email,
password: hashedPassword
})
await users.save()
res.redirect(‘/login’)

}

catch(err){
console.log(err)
res.redirect(‘/register’) }
})

El problema es cuando intento iniciar sesión con los datos de usuario almacenados, sigo recibiendo el siguiente error.

Error: se requieren argumentos de datos y hash
    en Object.compare (C:\AIT715\reactlogin\node_modules\bcrypt\bcrypt.js:208:17)
    en C:\AIT715\reactlogin\node_modules\bcrypt\promises.js:29:12
    en nueva promesa (<anónimo>)
    en Object.module.exports.promise (C:\AIT715\reactlogin\node_modules\bcrypt\promises.js:20:12)
    en Object.compare (C:\AIT715\reactlogin\node_modules\bcrypt\bcrypt.js:204:25)
    en Strategy.authenticateUser [como verificar] (C:\AIT715\reactlogin\passport-config.js:14:24)
    en processTicksAndRejections (internal/process/taskqueues.js:95:5)

He intentado hacer los siguientes cambios en el archivo passport-config.js, pero no ha funcionado.

const LocalStrategy = require(‘passport-local’).Strategy
const bcrypt = require(‘bcrypt’)
const User = require(‘./models/user’)

function initialize(passport, getUserByEmail, getUserById) {
const authenticateUser = async (email, password, done) => {
const user = await User.find({email:email});
console.log(user);
if (user == null) {
return done(null, false, { message: ‘No hay ningún usuario con ese correo electrónico’ })
}

try {
if (await bcrypt.compare(password, user.password)) {
return done(null, user)
} else {
return done(null, false, { message: ‘Contraseña incorrecta’ })
}
} catch (e) {
return done(e)
}
}

“`
Además, cuando utilizo console.log(user) puedo ver los datos, pero cuando intento console.log(user.email) obtengo undefined. ¿Alguien puede sugerir qué estoy haciendo mal aquí o qué cambios debo hacer en el archivo passport-config para que esto funcione? Cualquier ayuda es muy apreciada.</anónimo>

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Parece que el método User.find() devuelve un array de objetos y estás intentando comparar la contraseña con un array en lugar de con un objeto. Puedes intentar cambiar el código y usar el método User.findOne(), el cual debería devolver un solo objeto:

    const user = await User.findOne({ email: email });
    

    Y para acceder a la propiedad del correo electrónico, debes utilizar user[0].email o user.email si usas findOne().

    if (!user) {
      return done(null, false, { message: 'No existe ningún usuario con ese correo electrónico' });
    }
    
    try {
      if (await bcrypt.compare(password, user.password)) {
        return done(null, user);
      } else {
        return done(null, false, { message: 'Contraseña incorrecta' });
      }
    } catch (e) {
      return done(e);
    }
    

    Esto debería solucionar el error y permitirte comparar la contraseña con la contraseña del usuario correctamente.

Comments are closed.