passport-local-mongoose setPassword not working - node.js

Am trying to reset the user password, and am using passport-local-mongoose, and i send the reset link through mail for them and a token is added to the link also. the link opens but when user hits the reset button it throws up an error in my command line null
passortLocalMongoose = require("passport-local-mongoose")
var UserSchema = new mongoose.Schema({
email: {type: String, unique: true},
password: String,
resetPasswordToken: String,
resetpasswordExpires: Date
})
UserSchema.plugin(passortLocalMongoose);
mongoose.model("User", UserSchema )
app.post('/reset/:token', function(req, res, next) {
asynco.waterfall([
function(done) {
User.findOne({resetPasswordToken :req.params.token, resetPasswordExpires: { $gt: Date.now()}}, function(err, user) {
if(!user){
console.log(err);
req.flash('error', 'Password reset token is invalid or has expired')
return res.redirect('back')
}
if(req.body.password === req.body.confirm) {
user.setPassword(req.body.password, function(err,user){
if(err){
console.log(err)
req.flash('error', 'Sorry something went wrong')
return res.redirect('back')
} else {
user.resetPasswordToken = undefined;
user.resetPasswordExpires = undefined;
user.save(function(err){
req.login(user, function(err){
done(err,user)
})
})
}
})
} else {
req.flash('error', 'Passwords do not match')
res.redirect('back');
}
})
}
])
})
The error am getting when user hits the submit button
null
if i debug it just after the if(req.body.password == req.body.confirm) and type arguments it shows the two inputs are null but i type req.body it shows the two passwords

You forgot the semicolon. Is that your problem ?
app.post('/reset/:token', function(req, res, next) {
asynco.waterfall([
function(done) {
User.findOne({resetPasswordToken :req.params.token, resetPasswordExpires: { $gt: Date.now()}}, function(err, user) {
if(err){
console.log(err);
req.flash('error', 'Password reset token is invalid or has expired')
return res.redirect('back')
}
if(req.body.password === req.body.confirm) {
user.setPassword(req.body.password, function(err,user){
if(err){
console.log(err)
req.flash('error', 'Sorry something went wrong')
return res.redirect('back')
} else {
user.resetPasswordToken = undefined;
user.resetPasswordExpires = undefined;
user.save(function(err){
req.login(user, function(err){
done(err,user)
})
})
}
});
} else {
req.flash('error', 'Passwords do not match')
res.redirect('back');
}
});
}
])
})

Based on your information and code I can help you with assumptions only, provide more information and I'll update the answer.
Are you sure that user is found with your criteria?
User.findOne({
resetPasswordToken: req.params.token,
resetPasswordExpires: { $gt: Date.now()}
}, function(err, user) {
if (err) {} // Handle the error
if (!user) {} // User is not found, but no error as well
// only then try to call setPassword
});
I bet, your criteria is wrong and that is the reason why Mongo returns null instead of User record.
All you need to do to solve the problem is to debug that everything is writes in database and that your criteria is able to match the correct user. Everything else will work then.

Related

why this error is showing? cant set header after they sent to the client

this is mylogin code : you can see the token from here and the next photo is the auth for token
can anyone explain it please............................................................................................................................
const login = (req, res, next) => {
var username = req.body.username;
var password = req.body.password;
User.findOne({$or: [{email: username}, {phoneNumber: username}]})
.then(user => {
if (user) {
bcrypt.compare(password, user.password, function(err, result){
if (err) {
res.json({
title: 'Server error',
error: err
})
console.log('err');
}if (result){
const maxAge = 24 * 60 * 60
const createToken = jwt.sign({ _id: user._id } , process.env.TOKEN_SECRET, { expiresIn: maxAge });
res.header('auth-token',token);
}else{
return res.status(401).json({
title: 'password wrong',
error: 'invalid credentials'
})
}
})
}
else {
return res.status(401).JSON({
title: 'password wrong',
error: 'invalid credentials'
})
}
})
If you look at the bcrypt.compare callback the res.json is executed twice:
function(err, result) {
if (err) {
res.json({}) // ONE
}
if (result) {
// skipped
} else {
return res.status(401).json({ // TWO
title: 'password wrong',
error: 'invalid credentials'
})
}
}
Add a return statement in the if(err)
Using a linter would help you to avoid these oversight

How to fix "TypeError: cb is not a function" error for comparing passwords

I've been starting to add user authentication into my app and when adding the login route, i've been getting the error "TypeError: cb is not a function". I know it is coming from my login route as all my other routes work fine.
I have tried researching the issue and trying a few fixes that i've found but none have worked. So i'm starting to believe i've messed up somewhere and I can't find where.
Login Route:
router.post('/login', function (req, res) {
User.findOne({ username: req.body.username }, function (err, user) {
if (err || user == null) {
console.log(err);
res.redirect('/login');
}
if (!user.comparePassword(req.body.password)) {
req.flash('invalidDetails', 'Wrong username or password!');
res.redirect('/login');
} else {
req.session.userId = user._id;
req.flash('loggedIn', 'User ' + req.body.username + ' has been logged in!');
return res.redirect('/');
}
});
});
User Model:
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
bcrypt = require('bcrypt'),
SALT_WORK_FACTOR = 10;
var UserSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: true,
trim: true
},
username: {
type: String,
unique: true,
required: true,
trim: true
},
password: {
type: String,
required: true
}
});
UserSchema.statics.authenticate = function (email, password, callback) {
User.findOne({ email: email }).exec(function (err, user) {
if (err) {
return callback(err);
} else if (!user) {
var err = new Error('User not found.');
err.status = 401;
return callback(err);
}
bcrypt.compare(password, hash, function (err, result) {
if (result === true) {
return callback(null, user);
} else {
return callback();
}
});
});
};
UserSchema.pre('save', function (next) {
var user = this;
// only hash the password if it has been modified (or is new)
if (!user.isModified('password')) return next();
// generate a salt
bcrypt.genSalt(SALT_WORK_FACTOR, function (err, salt) {
if (err) return next(err);
// hash the password along with our new salt
bcrypt.hash(user.password, salt, function (err, hash) {
if (err) return next(err);
// override the cleartext password with the hashed one
user.password = hash;
next();
});
});
});
UserSchema.methods.comparePassword = function comparePassword(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, function (err, isMatch) {
if (err) {
return cb(err);
}
cb(null, isMatch);
});
};
var User = mongoose.model('User', UserSchema);
module.exports = User;
I'm expecting it to compare the password with the password that has been entered into the login form with the password that is stored in the database and log in the user if the password is correct or redirect back to the login page with the invalidDetails flash message if the password is incorrect.
But what i'm actually getting is the "TypeError: cb is not a function" error when trying to login.
You are not passing a callback that's why.
If you want a promise based method you can write something like this
AuthSchema.methods.comparePassword = function(candidatePassword) {
const currentPassword = this.password;
return new Promise((resolve, reject) => {
bcrypt.compare(candidatePassword, currentPassword, function(err, isMatch) {
if (err) return reject(err);
resolve(isMatch);
});
})
};
And now you can call that with await

change password in nodejs, mongoDB with passport

I'm using JWT with Passport for authentication in my app, but I don't know how to change the password.
This is my login function:
function login(req, res, next) {
const userObj = {
email: req.body.email,
userType: req.body.userType
};
UserSchema.findOneAsync(userObj, '+password')
.then((user) => {
if (!user) {
const err = new APIError('User not found with the given email id', httpStatus.NOT_FOUND);
return next(err);
} else {
user.comparePassword(req.body.password, (passwordError, isMatch) => {
if (passwordError || !isMatch) {
const err = new APIError('Incorrect password', httpStatus.UNAUTHORIZED);
return next(err);
}
user.loginStatus = true;
user.gpsLoc = [19.02172902354515, 72.85368273308545];
const token = jwt.sign(user, config.jwtSecret);
UserSchema.findOneAndUpdateAsync({ _id: user._id }, { $set: user }, { new: true })
.then((updatedUser) => {
const returnObj = {
success: true,
message: 'user successfully logged in',
data: {
jwtAccessToken: `JWT ${token}`,
user: updatedUser
}
};
res.json(returnObj);
})
.error((err123) => {
const err = new APIError(`error in updating user details while login ${err123}`, httpStatus.INTERNAL_SERVER_ERROR);
next(err);
});
});
}
})
.error((e) => {
const err = new APIError(`erro while finding user ${e}`, httpStatus.INTERNAL_SERVER_ERROR);
next(err);
});
}
my user DB is like this.
import Promise from 'bluebird';
import mongoose from 'mongoose';
import httpStatus from 'http-status';
import APIError from '../helpers/APIError';
import bcrypt from 'bcrypt';
const UserSchema = new mongoose.Schema({
fname: { type: String, default: null },
lname: { type: String, default: null },
email: { type: String, required: true, unique: true },
password: { type: String, required: true, select: false },
});
UserSchema.pre('save', function userSchemaPre(next) {
const user = this;
if (this.isModified('password') || this.isNew) {
bcrypt.genSalt(10, (err, salt) => {
if (err) {
return next(err);
}
bcrypt.hash(user.password, salt, (hashErr, hash) => {
if (hashErr) {
return next(hashErr);
}
user.password = hash;
next();
});
});
} else {
return next();
}
});
UserSchema.methods.comparePassword = function comparePassword(pw, cb) {
const that = this;
bcrypt.compare(pw, that.password, (err, isMatch) => {
if (err) {
return cb(err);
}
cb(null, isMatch);
});
};
I have made another function for reset password and matching checked old password is valid like login function, now I want to update new passport in DB. how will I do that?
Thanks a lot
I'm not sure what you're looking for here, but a changePassword function is just a simple update on UserSchema. Here is a sample:
function changePassword(req, res, next) {
// Init Variables
var passwordDetails = req.body;
if (req.user) {
if (passwordDetails.newPassword) {
UserSchema.findById(req.user.id, function (err, user) {
if (!err && user) {
if (user.authenticate(passwordDetails.currentPassword)) {
if (passwordDetails.newPassword === passwordDetails.verifyPassword) {
user.password = passwordDetails.newPassword;
user.save(function (err) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
req.login(user, function (err) {
if (err) {
res.status(400).send(err);
} else {
res.send({
message: 'Password changed successfully'
});
}
});
}
});
} else {
res.status(422).send({
message: 'Passwords do not match'
});
}
} else {
res.status(422).send({
message: 'Current password is incorrect'
});
}
} else {
res.status(400).send({
message: 'User is not found'
});
}
});
} else {
res.status(422).send({
message: 'Please provide a new password'
});
}
} else {
res.status(401).send({
message: 'User is not signed in'
});
}
};
Hope this helps!
You dont have to write any methods in schema. You can directly use ChangePassword function with schema like this
user.changePassword(req.body.oldpassword, req.body.newpassword, function(err)
{

How update the password in mongodb

app.get('/changePass', function(req, res) {
password = req.body.password;
password1 = req.body.password1;
xyz = req.body.xyz;
User.find({ email: xyz, password: password }, function(err, data) {
if (err) {
throw err;
}
if (data.length === 0) {
return res.json({ success: false, data: 'please enter valid
Old password' })
} else {
// User.update({ password: password }, {
// $set: {
// password: password1
// }
// });
var usr = new User();
usr.update({ "password":password }, password1, { upsert:true
});
//usr.password = password;
usr.save(function(err, data) {
if (err)
throw err;
return res.json({ success: true, data: 'password changed
successfully' });
})
}
})
how i update password in mongodb i am matching password to password and updating password to password1.this is giving me alert with please enter valid old password.
xyz is cookie that contains email.
You should use findOne on model to return userObject.
Then you can update the object that was found like regular javascript object and save it with .save function.
User.findOne({email: xyz, password: req.body.password1}, function(err, user){
if(err)return handleErr(err);
user.password = req.body.password2;
user.save(function(err){
if(err)return handleErr(err);
//user has been updated
});
});

Getting out of sync server response

On a successful signup of a user I am currently seeing a mostly empty page with the text undefined. Redirecting to /app at the top.
UPDATE: I should also mention that after form submittal I am redirected to /users. So on /users I see the text mentioned above.
I think it is because of the req.redirect call being within the user.save callback but I am not sure what the fix is.
I am using mongoose for the ORM.
var User = require('../models/user');
module.exports = function(app) {
app.post('/users', function(req, res, next) {
var user = new User({
email: req.body.email,
password: req.body.password
});
user.save(function(err) {
if (err)
res.send(412, {message: err});
else
req.login(user, function(err) {
if (err !== undefined) return next(err);
res.redirect('/app', {
email: user.email,
id: user._id
});
});
});
});
};
It turns out that the req.login call has to be contained in a password.authenticate callback. The example on the site left that part out.
user.save(function(err) {
if (err)
res.send(412, {message: err});
else
passport.authenticate('local', function(err, user) {
if (err) { return next(err) }
if (!user) { return res.redirect('/login') }
req.login(user, function(err) {
if (err) { return next(err); }
return res.redirect('/app', { email:user.email, id:user._id });
});
})(req, res, next);
});

Resources