app.post('/signup', passport.authenticate('local-signup', {
successRedirect: '/',
failureRedirect: '/signup',
failureFlash: true
}));
This is the route.
passport.use('local-signup', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
function(req, email, password, done) {
process.nextTick(function() {
User.findOne({ 'local.email': email }, function(err, user) {
if(err)
return done(err);
if(user) {
return done(null, false, req.flash('signupMessage', 'That email is already taken'));
} else {
var newUser = new User();
newUser.local.email = email;
newUser.local.password = newUser.generateHash(password);
newUser.save(function(err) {
done(err, user);
});
}
});
});
}));
This is the passport config file. The form is working as intended and being saved using my mongo schema, but it's using the failureRedirect instead of the successRedirect, anyone notice something wrong?
When you call the save function on your newly created user you forget to pass in a 2nd argument to its callback, which is the user document returned from the db.
From your current code logic the user in your last done function is referring to the callback from findOne and therefore will never get there since if there's a user coming back from the server at that point it will execute everything in if (user) { ... }.
Make sure to pass a second argument to save like this:
newUser.save(function(err, user) {
done(err, user);
});
Related
I have a pretty simple application that is just an auth service and a profile page with a logout button at this point. I am trying to signup a user, who is redirected to /profile and then I logout. All of this works fine. I also have a verification email in there too but that is currently besides the point.
My issue is that when I go to log into the site it gives me no error messages, nothing, just redirects me to /login which is what my passport strategy's meant to do if there is an error.
Can anyone spot an error in my code that would cause me not to log into the site? I have included what I think are the important parts of my application.
app.js
// PASSPORT CONFIGURATION
require('./controllers/passport')(passport);
app.use(passport.initialize());
app.use(passport.session());
require('./routes/index.js')(app, passport);
passport.js login strategy
passport.use('login', new LocalStrategy({
usernameField: 'email',
passReqToCallback : true
},
function(req, email, password, done) {
User.findOne({ 'email' : email },
function(err, user) {
if (err) return done(err);
if (!user){
return done(null, false, req.flash('error', 'User not found'));
}
user.comparePassword(password, function(err, isMatch) {
if(err){
console.log(err);
}
if (isMatch) {
// Make sure the user has been verified
if (!user.isVerified) return done (null, false, req.flash('error', 'Your account has not been verified.' ));
var time = 14 * 24 * 3600000;
req.session.cookie.maxAge = time; //2 weeks
req.session.cookie.expires = new Date(Date.now() + time);
req.session.touch();
return done(null, user, req.flash('success', 'Successfully logged in.'));
} else {
return done(null, false, req.flash('error', 'Invalid Password'));
}
});
}
);
})
);
login route
app.post('/login', passport.authenticate('login', {
successRedirect : '/profile',
failureRedirect : '/login',
failureFlash : true
}));
user.js model
var UserSchema = new mongoose.Schema({
email: String,
password: String,
role: String,
avatar: String,
isVerified: { type: Boolean, default: false },
resetPasswordToken: String,
resetPasswordExpires: Date
});
UserSchema.plugin(passportLocalMongoose, { usernameField : 'email' });
UserSchema.plugin(timestamps);
UserSchema.pre('save', function(next) {
var user = this;
if (!user.isModified('password')) return next();
bcrypt.genSalt(10, function(err, salt) {
if (err) return next(err);
bcrypt.hash(user.password, salt, null, function(err, hash) {
if (err) return next(err);
user.password = hash;
next();
});
});
});
UserSchema.methods.comparePassword = function(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
if (err) return cb(err);
cb(null, isMatch);
});
};
I am not sure how this solved it but it did... I added in my auth middleware that checks if a user should be able to access the page or not and now I can log in. Here is my middleware that checks it.
middleware
exports.isUnauthenticated = function(req, res, next) {
if (!req.isAuthenticated()){
return next();
}
res.redirect('/');
};
Then I just required it and updated my post route to be
post login route
app.post('/login', isUnauthenticated, passport.authenticate('login', {
successRedirect : '/profile',
failureRedirect : '/login',
failureFlash : true
}));
I am using Passport and Express in a NodeJs project.
I have a User model with fields: id, password, and email. When I try to signup it throws this error:
[object Object]
into the form and it doesn't post user data in the database. In the console, it shows
POST /signup 302 -58.
Here's whole passport.js file:
var LocalStrategy = require('passport-local').Strategy;
// load up the user model
var configDB = require('./database.js');
var Sequelize = require('sequelize');
var sequelize = new Sequelize(configDB.url);
var User = sequelize.import('../app/models/users');
User.sync();
// load the auth variables
var configAuth = require('./auth'); // use this one for testing
module.exports = function(passport) {
// used to serialize the user for the session
passport.serializeUser(function(user, done) {
done(null, user.id);
});
// used to deserialize the user
passport.deserializeUser(function(id, done) {
User.findById(id).then(function(user){
done(null, user);
}).catch(function(e){
done(e, false);
});
});
=========================================================================
// LOCAL LOGIN =============================================================
passport.use('local-login', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true // allows us to pass in the req from our route (lets us check if a user is logged in or not)
},
function(req, email, password, done) {
User.findOne({ where: { email: email }})
.then(function(user) {
if (!user) {
done(null, false, req.flash('loginMessage', 'Unknown user'));
} else if (!user.validPassword(password)) {
done(null, false, req.flash('loginMessage', 'Wrong password'));
} else {
done(null, user);
}
})
.catch(function(e) {
done(null, false, req.flash('loginMessage',e.name + " " + e.message));
});
}));
=========================================================================
// LOCAL SIGNUP ============================================================
passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true // allows us to pass in the req from our route (lets us check if a user is logged in or not)
},
function(req, email, password, done) {
// Whether we're signing up or connecting an account, we'll need
// to know if the email address is in use.
User.findOne({ where: { email: email }})
.then(function(existingUser) {
// check to see if there's already a user with that email
if (existingUser)
return done(null, false, req.flash('error', 'That email is already taken.'));
// If we're logged in, we're connecting a new local account.
if(req.user) {
var user = req.user;
user.email = email;
user.password = User.generateHash(password);
user.save().catch(function (err) {
throw err;
}).then (function() {
done(null, user);
});
}
// We're not logged in, so we're creating a brand new user.
else {
// create the user
var newUser = User.build ({email: email, password: User.generateHash(password)});
newUser.save().then(function() {done (null, newUser);}).catch(function(err) { done(null, false, req.flash('error', err));});
}
})
.catch(function (e) {
done(null, false, req.flash('loginMessage',e.name + " " + e.message));
})
}));
And in routes.js
// locally --------------------------------
// LOGIN ===============================
// show the login form
app.get('/login', function(req, res) {
res.render('login.ejs', { message: req.flash('loginMessage') });
});
// process the login form
app.post('/login', passport.authenticate('local-login', {
successRedirect : '/profile', // redirect to the secure profile section
failureRedirect : '/login', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}));
// SIGNUP =================================
// show the signup form
app.get('/signup', function(req, res) {
res.render('signup.ejs', { message: req.flash('loginMessage') });
});
// process the signup form
app.post('/signup', passport.authenticate('local-signup', {
successRedirect : '/profile', // redirect to the secure profile section
failureRedirect : '/signup', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}));
Thanks in advance.
I found the solution!!! It was simpler than I thought, just a carelessness.
In user model I defined password field:
password: {
type: DataTypes.STRING(25),
allowNull: true,
defaultValue: ''
},
And after encryption, this field length was too small to storage the value. So I changed it for 255.
I have a user table in which i have an Admin account and some other normal users accounts.
I want to do all activities which for a particular user. It should act like that activity done by same user.
Can somebody tell me how can i switch to another account from Admin account
without login to that account.
Currently i use passport authentication.(passport-local)
Here is my code
app.get('/secure/group/login', function(req,res,next) {
passport.authenticate('local',function(err,user,info) {
console.log("error is "+err);
req.logIn('tessAccount',function(err) {
console.log("Weer" +err);
});
console.log("dd");
})(req,res,next);
});
});
and passport code
var LocalStrategy = require('passport-local').Strategy;
module.exports = function(passport) {
// used to serialize the user for the session
passport.serializeUser(function(user, done) {
done(null, user.token);
});
passport.use(new BearerStrategy(
function(token, done) {
user.tokenExist(token, function(err, user) {
if (err) {
return done(err);
}
else {
return done(null, user, { scope: 'all' });
}
});
}
));
// used to deserialize the user
passport.deserializeUser(function(accessToken, done) {
user.getUserByAccessToken(accessToken, function(err, dbUser) {
if (err) {
done(err);
} else {
done(null, dbUser[0]);
}
});
});
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'
passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) {
user.emailExists(email, function(err, exists) {
if (err)
return done(err);
else if (exists) {
return done(null, false, {
message: req.flash('loginMessage')
});
} else {
req.userDetails.status = 0;
req.userDetails.token = md5.digest_s(req.userDetails.email + new Date());
req.userDetails.userImage = config.user.image;
user.register(req.userDetails, function(err, newUser) {
if (err)
return done(err);
else {
/*Get user Shared article if exist start*/
getSharedArticlesOfnewlyuserIfExist(email, newUser.insertId);
/*Get user Shared article if exist end*/
req.userDetails.id = newUser.insertId;
return done(err, req.userDetails);
}
});
}
});
}));
passport.use('local-login', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) {
// callback with email and password from our form
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
user.matchPassword({
email: email,
password: password
}, function(err, newUser) {
// if there are any errors, return the error before anything else
if (err)
return done(err);
// if no user is found, return the message
if (newUser.length > 0) {
var user = {
id: newUser[0].user_id,
email: newUser[0].email_id,
token: newUser[0].user_access_token
};
return done(null, user);
} else {
return done(null, false, {
message: 'Incorrect username or password.'
}); // req.flash is the way to set flashdata using connect-flash
}
});
}));
User.findOne({ username: 'Myusername' }, function(err, user) {
req.logIn(user, function(err){});
});
This worked for me to log into an account without using password, it switches from my admin account to an user account.
Actually I'm using passport.js and mongoose
So I am trying to add local authentication to my MEAN stack app.
Everything was running smoothly. Sign up works great. But I cannot log in as a user.
I am getting:
POST /login 302 3.979 ms - 58
on the console (via Morgan)
But there is certainly an error (express routes to the "failureRedirect" set via passport)
Could it be a problem reading from the db? Why would I be able to write to it then...
A test with chai reveals that the program cannot "find user by email" from the db via User Model
anyone have any clue why this is happening?
Here is my passport strategy code:
/config/passport.js
var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/users');
module.exports = function(passport) {
// passport session setup ==================================================
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
// local login =============================================================
passport.use('local-login', new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(req, email, password, done) {
User.findOne({ 'local.email' : email }, function(err, user) {
if (err)
return done(err);
if (!user)
return done(null, false, req.flash('loginMessage', 'No user found.'));
if (!user.validPassword(password))
return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.'));
return done(null, user);
});
}));
// local sign up =============================================================
passport.use('local-signup', new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(req, email, password, done) {
User.findOne({ 'local.email' : email }, function(err, user) {
if (err)
return done(err);
if (user) {
return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
} else {
var newUser = new User();
newUser.local.email = email;
newUser.local.password = newUser.generateHash(password); // use the generateHash function in our user model
newUser.save(function(err) {
if (err)
throw err;
return done(null, newUser);
});
}
});
}));
};
Here's the routes:
// /login ======================================================================
app.route('/login')
.get(function(req, res) {
res.setHeader('Content-Type', 'text/html');
res.render('login.html');
})
.post(passport.authenticate('local-login', {
successRedirect : '/profile',
failureRedirect : '/'
}));
// /signup ======================================================================
app.route('/signup')
.get(function(req, res) {
res.setHeader('Content-Type', 'text/html');
res.render('signup.html');
})
.post(passport.authenticate('local-signup', {
successRedirect : '/profile',
failureRedirect : '/'
}));
Login Strategy
// passport/login.js
passport.use('login', new LocalStrategy({
passReqToCallback : true
},
function(req, username, password, done) {
// check in mongo if a user with username exists or not
User.findOne({ 'username' : username },
function(err, user) {
// In case of any error, return using the done method
if (err)
return done(err);
// Username does not exist, log error & redirect back
if (!user){
console.log('User Not Found with username '+username);
return done(null, false,
req.flash('message', 'User Not found.'));
}
// User exists but wrong password, log the error
if (!isValidPassword(user, password)){
console.log('Invalid Password');
return done(null, false,
req.flash('message', 'Invalid Password'));
}
// User and password both match, return user from
// done method which will be treated like success
return done(null, user);
}
);
}));
We now define our routes for the application in the following module which takes the instance of Passport created in app.js above. Save this module in
module.exports = function(passport){
/* GET login page. */
router.get('/', function(req, res) {
// Display the Login page with any flash message, if any
res.render('index', { message: req.flash('message') });
});
/* Handle Login POST */
router.post('/login', passport.authenticate('login', {
successRedirect: '/home',
failureRedirect: '/',
failureFlash : true
}));
/* GET Registration Page */
router.get('/signup', function(req, res){
res.render('register',{message: req.flash('message')});
});
/* Handle Registration POST */
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/home',
failureRedirect: '/signup',
failureFlash : true
}));
return router;
}
I am trying to redirect a user once he signs up or if the username is already present in the db, the function works well but I can not redirect and I am totally confused on what to do next.
Here is my passport file
var LocalStrategy = require('passport-local').Strategy;
var User = require('./models/user');
module.exports = function(passport) {
passport.serializeUser(function(user, done) {
done(null, user);
});
// used to deserialize the user
passport.deserializeUser(function(user, done) {
done(null, user);
});
passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) {
// asynchronous
// User.findOne wont fire unless data is sent back
process.nextTick(function() {
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
User.findOne({ 'email' : email }, function(err, user) {
// if there are any errors, return the error
if (err) {
return done(err);
}
if(user) {
if(user.validPassword(password)) {
return done(null, user);
} else {
return done(null, true, req.flash('signupMessage', 'That email is already in DB.'));
}
} else {
var newUser = new User();
newUser.email = email;
newUser.password = newUser.generateHash(password);
newUser.save(function(err) {
if (err)
return done(err);
return done(null, newUser);
});
}
});
});
}));
}
and my route
app.post('/signup',passport.authenticate('local-signup', {
successRedirect : '/timeslot', // redirect to the secure profile section
failureRedirect : '/', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}));
I have also tried doing
app.post('/signup',function(req, res, next) {
passport.authenticate('local-signup', function(err, user, info) {
if (user) {
res.redirect('/timeslot');
}
else res.redirect('/');
})(req, res, next);
});
but it is not working at all. I am desperate to fix this but dont know how.
I met the same problems with passport redirects. So my code began work just as
app.get("/auth/facebook/callback", passport.authenticate("facebook", { failureRedirect: config.loginPage }), function(req,res) {
res.redirect(config.redirectAfterLogin);
});