I am trying to make an authentication system for my website.
But when trying to log in with any combination I am receiving the following error in the website:
ReferenceError: user is not defined
user is not defined
ReferenceError: user is not defined
at Strategy._verify (/home/jarno/0__projects/nodejs/EasyOrders/routes/users.js:76:36)
at Strategy.authenticate (/home/jarno/0__projects/nodejs/EasyOrders/node_modules/passport-local/lib/strategy.js:90:12)
at attempt (/home/jarno/0__projects/nodejs/EasyOrders/node_modules...
In the console:
POST /users/login 500 204.677 ms - 3063
events.js:160
throw er; // Unhandled 'error' event
^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:356:11)
at ServerResponse.header (/home/jarno/0__projects/nodejs/EasyOrders/node_modules/express/lib/response.js:719:10)...
My code:
Users.js
passport.use(new LocalStrategy({
usernameField: 'email'
},
function(email, password, done) {
User.getUserByEmail(email, function(err, user) {
if(err) throw err;
if(!user) {
return done(null, false, {message: 'Unknown User'});
}
});
User.comparePassword(password, user.password, function(err, isMatch) {
if(err) throw err;
if(isMatch) {
return done(null, user);
} else {
return done(null, false, {message: 'Invalid password'});
}
});
}
));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.getUserById(id, function(err, user) {
done(err, user);
});
});
router.post('/login',
passport.authenticate('local', {successRedirect: '/', failureRedirect:'/users/login', failureFlash: true}),
function(req, res) {
res.redirect('/');
});
module.exports = router;
User.js model:
var UserSchema = mongoose.Schema({
email: {
type: String,
index: true
},
name: {
type: String
},
password: {
type: String
},
});
var User = module.exports = mongoose.model('User', UserSchema);
module.exports.createUser = function(newUser, callback) {
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(newUser.password, salt, function(err, hash) {
newUser.password = hash;
newUser.save(callback);
});
});
}
module.exports.getUserByEmail = function(email, callback) {
var query = {email: email};
User.findOne(query, callback);
}
module.exports.getUserById = function(id, callback) {
User.findById(id, callback);
}
module.exports.comparePassword = function(candidatePassword, hash, callback) {
bcrypt.compare(candidatePassword, hash, function(err, isMatch) {
if(err) throw err;
callback(null, isMatch);
});
}
The problem is here:
User.getUserByEmail(email, function(err, user) {
if(err) throw err;
if(!user) {
return done(null, false, {message: 'Unknown User'});
}
});
User.comparePassword(password, user.password, function(err, isMatch) {
if(err) throw err;
if(isMatch) {
return done(null, user);
} else {
return done(null, false, {message: 'Invalid password'});
}
});
You are trying to use user.password when it's not already defined.
You need to nest the User.comparePassword function inside User.getUserByEmail or properly resolve it using promises.
Well the prompted message show that the user is not defined. It's the message error throwns in users.js .I think, You forgot to mention the name of your passport strategie that you have defined. Your code in users.js should be like this :
passport.use('local', new LocalStrategy({.......})
Related
If you have a react application and don't wanna use connect-flash to access the messages generated by the local strategy you can use the following:
My passport local strategy, I am using a sqlite db:
passport.use(
new LocalStrategy({ usernameField: 'name' },
(name, password, done) => {
//Match user
db.get(`SELECT * FROM Users WHERE name = '${name}'`, (err, user) => {
if(err) throw err;
if(!user) {
return done(null, false, { message : 'Username not registered' });
}
//Match password
bcrypt.compare(password, user.password, (err, isMatch) => {
if(err) throw Error;
if(isMatch) {
done(null, user, { message : 'Log in successful' });
} else { done(null, false, { message : 'Password incorrect' })
}
});
})
})
);
You can use a custom call back function for your /login route:
app.post('/login', (req, res, next) => {
passport.authenticate('local', (err, user, info) => {
if (err) { return next(err); }
if (!user) { return res.json(info); }
req.logIn(user, (err) => {
if (err) { return next(err); }
return res.json(info);
});
})(req, res, next);
});
The info argument contains the object passed as a third argument in done() from the strategy and can be added to the body of res and therefore used by react.
I'm havig trouble understanding how to access the properties of a global variable that is set in the middleware of my application
// app.js
app.use(function (req, res, next) {
res.locals.user = req.user || null;
next();
});
I would have thought I could access the req.user.username in my template (using handlebars), but for some reason it is forcing me to iterate over this object.
A consle.log(req.user) shows:
_id: 5f01f9a861f5b33b42a9e,
username: 'onetap',
email: 'test#gmail.com',
password: '$2b$10$VLBS8ZwPKiaXasdfsiiwfg.wyJ1J5CwTKLjS5zXwAsvukHpNmk0HG2',
createdAt: 2020-07-05T16:02:48.081Z,
__v: 0
}
And in my template I have to use an each loop and can't access the properties directly. the req.user is not an array either.
{{user.username}}//undefined
{{#each user}}
{{username}} //onetap
{{/each}}
passport.js file
const LocalStrategy = require("passport-local").Strategy;
const bcrypt = require("bcrypt");
const mongoose = require("mongoose");
// Load User Model
const User = require("../models/User");
module.exports = function (passport) {
passport.use(
new LocalStrategy({ username: "username" }, (username, password, done) => {
// Match User
User.findOne({
username: username,
}).then((user) => {
if (!user) {
return done(null, false, { message: "Invalid Username" });
}
console.log("Checking password");
// Match password
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: "Password incorrect" });
}
});
});
})
);
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
};
I was able to fix this by chaning deserialize to:
passport.deserializeUser(function (id, done) {
User.findById(id)
.lean()
.exec(function (err, user) {
done(err, user);
});
});
I'm new to SO & Node / Passport so apologies in advance. I've been trying to work through the login portion of my site using Passport (already have registration working) for several days now with no success. I've tried several tutorials and read through the documentation, but at this point am more confused than when I started.
Problem: passport.authenticate function returns "user" as false despite the information being correct according to my database (MongoDB). I'm not getting any error messages, in /dologin route, the user value is false and info value is "Missing Credentials". Let me know if there is any other information I can provide - I appreciate the help!
Attempts: I've moved my code around to different functions, files etc. Tried different solutions found online, tried the documentation examples, wrote my own methods in my models. etc.
App.js file
app.use(session({
secret: 'secrettexthere',
saveUninitialized: true,
resave: true,
// using store session on MongoDB using express-session + connect
store: new MongoStore({
mongooseConnection: mongoose.connection
})
}));
// Init passport authentication
app.use(passport.initialize());
// persistent login sessions
app.use(passport.session());
passport.use(new LocalStrategy(
function(username, user_password, done) {
User.getUserByUsername(username, function(err,user){
console.log('in getUserByUsername');
if(err) throw err;
if(!user){
return done(null, false, {message: 'Unknown user.'});
};
User.comparePassword(password, user.password, function(err,isMatch) {
if (err) throw err;
console.log('in comparepassword');
if(isMatch) {
console.log('isMatch');
return done(null, user);
} else { console.log('not match');
done(null, false, {message:'Invalid username or password.'})};
})
});
} ));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.getUserById(id, function(err, user) {
done(err, user);
});
});
Routing File (ideally will eventually move this to my controller but just want to get it working to some extent to start)
router.post('/dologin', function(req, res, next) {
console.log(req);
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { console.log('nomatch');
console.log(info);
console.log('');
console.log(user);
return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
console.log('match match match');
return res.redirect('/register');
});
})(req, res, next);
});
Model
module.exports.getUserByUsername = function(username, callback){
var query = {username: username};
User.findOne(query, callback);
};
module.exports.comparePassword = function(candidatePassword, hash, callback){
bcrypt.compare(candidatePassword, hash, function(err,isMatch){
if (err) throw err;
callback(null, isMatch);
});
};
module.exports.getUserById = function(id, callback){
User.findById(id, callback);
};
I need a way to compare two hashed passwords before performing a post request in node js. The hashed password is stored in a mongoDB database. I've narrowed my mistake down to these possible areas.
//Part 1
router.post('/signIn', function (req, res) {
if(errors){
console.log(errors);
res.render('signIn', {
errors: errors
});
}else {
module.exports = function (passport) {
passport.authenticate('local',{successRedirect: '/dashboard', failureRedirect: '/', failureFlash: true})
},
module.exports = function (passport) {
passport.use(new LocalStrategy(
function (username, password, done) {
User.getUserByUsername(inputUser, function (err, user) {
if (err) throw err;
if (!user) {
req.flash('error_msg','Unknown Username');
return done(null, false);
}
User.comparePassword(inputPwd, user, hash, function (err, isMatch) {
if (err) throw err;
if (isMatch) {
req.flash('error_msg','Unknown Password');
return done(null, user);
} else {
return done(null, false);
}
})
})
}))
},
module.exports = function (passport) {
passport.serializeUser( function (user, done) {
done(null, user.id());
});
},
module.exports = function (passport) {
passport.deserializeUser( function (id, done) {
User.getUserById(id, function (err, user) {
done(err, user);
});
});
};
res.redirect('/users/dashboard');
}
});
These parts are from different files.
//Part 2:
module.exports.createUser = function (newUser, callback) {
bcrypt.hash(newUser.password, 10, function(err, hash) {
newUser.password = hash;
newUser.save(callback);
});
}
module.exports.getUserByUsername = function (username, callback) {
var query = {username: username};
User.findOne(query, callback);
}
module.exports.comparePassword = function (password, hash, callback ) {
bcrypt.compare(password, hash, function(err, isMatch) {
if (err) throw err;
callback(null, isMatch);
console.log(isMatch);
});
}
Ok, you have made quite some mistakes, i hope i found all. I will go through them via comments in your code:
function (username, password, done) {
// inputUser is undefined, shouldn't that be username?
User.getUserByUsername(inputUser, function (err, user) {
if (err) throw err; // you should never throw in async callbacks! use done(err) instead
if (!user) {
req.flash('error_msg','Unknown Username');
return done(null, false);
}
// all your input arguments are undefined! Where does inputPwd, user and has coe from?
// inputPassword should be password i guess, hash idk, maybe user.hash?
// also your arguments are wrong
User.comparePassword(inputPwd, user, hash, function (err, isMatch) {
if (err) throw err; // again, don't throw!
if (isMatch) {
req.flash('error_msg','Unknown Password');
return done(null, user);
} else {
return done(null, false);
}
})
})
}));
Now a corrected version:
function (username, password, done) {
User.getUserByUsername(username, function (err, user) {
if (err) return done(err);
if (!user) {
req.flash('error_msg','Unknown Username');
return done(null, false);
}
User.comparePassword(password, user.password, function (err, isMatch) {
if (err) return done(err);
if (isMatch) {
req.flash('error_msg','Unknown Password');
return done(null, user);
} else {
return done(null, false);
}
})
})
}));
I set-up passport on nodejs with mongoose for allowing users to login and create new accounts. Create new account is working but the login part doesn't.
users.js
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var mongoose = require('mongoose');
var User = require('../models/user');
router.get('/login', function(req, res, next) {
res.render('login', {
'title': 'Login'
});
});
passport.serializeUser(function(user, done){done(null, user);});
passport.deserializeUser(function(id, done){
User.getUserById(id, function(err, user){
done(err, user);
});
});
passport.use(new LocalStrategy(
function(username, password, done){
User.getUserByUsername(username, function(err, user){
if(err) throw err;
if(!user){
console.log('Unknown User');
return done(null, false,{message: 'Unknown User'});
}
User.comparePassword(password, user.password, function(err, isMatch){
if(err) throw err;
if(isMatch){
return done(null, user);
}else{
console.log('Invalid Password');
return done(null, false, {message: 'Invalid password'});
}
});
});
}
));
router.post('/login', passport.authenticate('local', {successRedirect: '/',failureRedirect: '/users/register', failureFlash:'Invalid username or password'}), function(req,res){
console.log('Authentication Successful');
req.flash('success', 'You are logged in');
res.redirect('/');
});
../models/user.js
var mongoose = require('mongoose');
var bcrypt = require('bcrypt');
mongoose.connect('mongodb://localhost/nodeauth');
var db = mongoose.connection;
var UserSchema = mongoose.Schema({
username: {
type: String,
index: true
},
password: {
type: String, required: true, bcrypt: true
},
email:{
type: String
},
name:{
type: String
},
profileimage:{
type: String
}
});
var User = module.exports = mongoose.model('User', UserSchema);
module.exports.comparePassword = function(candidatePassword, hash, callback){
bcrypt.compare(candidatePassword, hash, function(err, isMatch){
if(err) return callback(err);
callback(null,isMatch);
});
}
module.exports.getUserById = function(id, callback){
User.findById(id, callback);
}
module.exports.getUserByUsername = function(username, callback){
var query = {username: username};
User.findOne(query, callback);
}
module.exports.createUser = function(newUser, callback){
bcrypt.hash(newUser.password, 10, function(err, hash){
if(err) throw err;
// Set hashed pw
newUser.password = hash;
// Create User
newUser.save(callback);
});
}
If I create the new user than is working the data are uploading the MongoDB but if I try to Log In it just drop me to the /users/register page I do not have any error
Well it is not doing anything because your login route is not calling anything... check the documentation on http://passportjs.org/docs to see how passport works.
In user.js you need something like
router.get('/login',
passport.authenticate('local'),
function(req, res) {
res.render('login', {
'title': 'Login'
});
});
Then in a separate file you need to setup your authentication strategy, for example:
var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy;
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, { message: 'Incorrect username.' });
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}
));
Check this tutorial for a step-by-step on implementing local authentication strategy.
http://code.tutsplus.com/tutorials/authenticating-nodejs-applications-with-passport--cms-21619
If you want something more advanced, this code has examples of social authentication strategies (for example, your users can log in using Facebook accounts)
https://github.com/mjhea0/passport-examples
Good luck!