'Authentication error with passport-mongoose-local
I am trying to use passport-local-mongoose to authenticate a user. I keep getting a validation error that the password is missing for my user anytime I try logging in. My app.js file content is as follows:
const express = require('express');
const bodyParser = require('body-parser');
const ejs = require('ejs');
const mongoose = require('mongoose');
const session = require('express-session');
const passport = require('passport');
const passportLocalMongoose = require('passport-local-mongoose');
const url = `mongodb://127.0.0.1:27017/secretsDB`;
const port = process.env.PORT ? process.env.PORT : 4000;
require('dotenv').config();
const app = express();
app.use(express.static(`${__dirname}/public`));
app.use(bodyParser.urlencoded({extended: true}))
app.set('view engine', 'ejs');
app.use(session({
secret: process.env.SECRET,
resave:false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
mongoose.connect(url, {useNewUrlParser: true, useUnifiedTopology: true});
mongoose.set('useCreateIndex', true);
const userSchema = new mongoose.Schema({
username: {
type: String,
required: true
},
password: {
type: String,
required: true
}
});
userSchema.plugin(passportLocalMongoose);
const User = new mongoose.model('User', userSchema);
passport.use(User.createStrategy());
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.get('/', (req, res) => {
res.render('home');
});
app.get('/login', (req, res) => {
res.render('login');
});
app.get('/register', (req, res) => {
res.render('register');
});
app.get('/secrets', (req, res) => {
if(req.isAuthenticated()) {
res.render('secrets');
} else {
res.redirect('/login');
}
});
app.get('/logout', (req, res) => {
req.logout();
res.redirect('/');
});
app.post('/register', (req, res) => {
User.register({username: req.body.username}, req.body.password, (err, user) => {
if(err) {
console.log(err);
res.redirect('/register');
} else {
passport.authenticate('local')(req, res, () => {
res.redirect('/secrets');
});
}
});
});
app.post('/login', (req, res) => {
const user = new User({
username: req.body.username,
password: req.body.password
});
req.login(user, (err) => {
if(err) {
console.log(err);
} else {
passport.authenticate('local')(req, res, () => {
res.redirect('/secrets');
});
}
})
});
app.listen(port, () => {
console.log(`app is listening on ${port}`);
});
My github repository contains the entire project
The error in the console is as follows:
Error: User validation failed: password: Path `password` is required.
at ValidationError.inspect (/home/anthony/Documents/Code/Angela/Secrets/node_modules/mongoose/lib/error/validation.js:48:26)
at formatValue (internal/util/inspect.js:703:31)
at inspect (internal/util/inspect.js:272:10)
at formatWithOptions (internal/util/inspect.js:1887:40)
at Object.Console.<computed> (internal/console/constructor.js:284:10)
at Object.log (internal/console/constructor.js:294:61)
at /home/anthony/Documents/Code/Angela/Secrets/app.js:80:21
at /home/anthony/Documents/Code/Angela/Secrets/node_modules/passport-local-mongoose/index.js:247:59
at processTicksAndRejections (internal/process/task_queues.js:97:5) {
errors: {
password: ValidatorError: Path `password` is required.
at validate (/home/anthony/Documents/Code/Angela/Secrets/node_modules/mongoose/lib/schematype.js:1178:13)
at /home/anthony/Documents/Code/Angela/Secrets/node_modules/mongoose/lib/schematype.js:1161:7
at Array.forEach (<anonymous>)
at SchemaString.SchemaType.doValidate (/home/anthony/Documents/Code/Angela/Secrets/node_modules/mongoose/lib/schematype.js:1106:14)
at /home/anthony/Documents/Code/Angela/Secrets/node_modules/mongoose/lib/document.js:2387:18
at processTicksAndRejections (internal/process/task_queues.js:79:11) {
properties: [Object],
kind: 'required',
path: 'password',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true
}
},
_message: 'User validation failed'
}
I have looked through my code, done google searches but I can't seem to find the answer. Can any one help.
Solution 1:[1]
instead of passport.use(User.createStrategy());
do something like this:
passport.use(new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.verifyPassword(password)) { return done(null, false); }
return done(null, user);
});
}
));
then you can authenticate protected routes routes like:
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
});
Solution 2:[2]
This morning, I had the idea to play with the required attribute in the mongoose schema, so I deleted the required attribute from the password field and voila, the code is working. This is interesting. Why do you think the password required field was causing this error? I think I found the reason why but if there's any other reason please feel free to let me know, in the database, passport creates a salt and hash entry instead of a password entry so by making password required in the schema, the code threw an error because it no longer existed.
Solution 3:[3]
You just have to remove required property from userSchema for both email as well well as your password because passport will take care of it and there is no field entry for password in database.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Karl L |
| Solution 2 | Anthony |
| Solution 3 | Tripathi Adarsh |
