Okay so I have implemented passportjs EXACTLY like my other projects which work perfectly, but for some reason in my current project I just cant get it to success/failure redirect.
Here's my code
route
app.post('/login', passport.authenticate('login', {
successRedirect: '/#1',
failureRedirect: '/#2',
failureFlash: true
}));
app.post('/login',
passport.authenticate('login', {failureRedirect: '/login'}),
function (req, res) {
console.log("logged");
res.redirect('/#1');
});
^ I tried it two different ways,in the second way, the 'logged' did not get logged..
Passport
//SIGN IN
passport.use('login', new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true
},
function (req, username, password, done) {
User.findOne({'username': username}, function (err, user) {
console.log("found: " + user);
if (err) {
console.log(err);
}
if (!user) {
return done(null, false, req.flash('message', 'Username not in DB'));
}
if (!user.checkPass(password)) {
return done(null, false, req.flash('message', 'Incorrect Password'));
}
//return user if all of the above pass
return done(null, user);
});
}));
EDIT: the passport code does work well, meaning it goes right towards the end and I can console.log the correct user.
Related
The ideal condition is while in route '/login/users', showing 'Please login first'. And after typing, if eamil or password is not suitable, showing 'This email is not registered!' or 'Email or Password is incorrect. But, Not knowing how to make it work. The real condition only shows 'Please login first' on every condition above.
I try to rewrite req.flash('errors') as req.flash('errors', ' '). Error shows with two commas in the begining and the end. But it comes another problem: while in this route '/login/users', Error seciton still shows with no content.
How to display login error with req.flash or fix the problem of Error section?
app.js
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: true
}))
app.use(bodyParser.urlencoded({ extended: true }))
app.use(express.static('public'))
app.use(methodOverride('_method'))
usePassport(app)
app.use(flash())
app.use((req, res, next) => {
res.locals.isAuthenticated = req.isAuthenticated()
res.locals.user = req.user
res.locals.success_msg = req.flash('success_msg')
res.locals.warning_msg = req.flash('warning_msg')
res.locals.error = req.flash('error', ' ')
res.locals.errors = req.flash('errors')
next()
})
app.use(routes)
congfig/passport.js
module.exports = app => {
app.use(passport.initialize())
app.use(passport.session())
passport.use(new LocalStrategy({
usernameField: 'email',
passReqToCallback: true,
}, (req, email, password, done) => {
User.findOne({ email })
.then(user => {
if (!user) {
return done(null, false, req.flash('error', 'This email is not registed!'))
}
return bcrypt.compare(password, user.password)
.then(isMatch => {
if (!isMatch) {
return done(null, false, req.flash('error', 'Email or Password incorrect.'))
}
return done(null, user)
})
.catch(err => done(err, false))
})
}))
middleware/auth.js
module.exports = {
authenticator: (req, res, next) => {
if (req.isAuthenticated()) {
return next()
}
req.flash('warning_msg', 'Please login first!')
res.redirect('/users/login')
}
}
routes/models/user.js
router.get('/login', (req, res) => {
res.render('login', { error: req.flash('error') })
})
router.get('/register', (req, res) => {
res.render('register')
})
router.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/uses/login',
failureFlash: true,
}))
The ideal condition is while in route '/login/users', showing 'Please login first'. And after typing, if eamil or password is not suitable, showing 'This email is not registered!' or 'Email or Password is incorrect. But, Not knowing how to make it work. The real condition only shows 'Please login first' on every condition above.
I try to rewrite req.flash('errors') as req.flash('errors', ' '). Error shows with two commas in the begining and the end. But it comes another problem: while in this route '/login/users', Error seciton still shows with no content.
How to display login error with req.flash or fix the problem of Error section?
I got some issues with a Node Express app. It will not redirect when I removed successRedirect property in auth method by passport.
The code below will not redirect to the desired page if I removed the successRedirect, and replacing it with a callback funtction.
The default code from defaultController.js
// passport local strategy
passport.use(new LocalStrategy({
usernameField: 'email',
passReqToCallback: true,
}, (req, email, password, done)=>{
User.findOne({ email:email }).then(user=>{
if(!user){
return done(null, false, req.flash('error-message', 'User not found with this email.'));
}
bcrypt.compare(password, user.password, (err, passwordMatched)=>{
if(err){
return err;
}
if(!passwordMatched){
return done(null, false, req.flash('error-message', 'Invalid username or password.'));
}
return done(null, user, req.flash('success-message', 'Login successful'));
});
});
}));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
router.route('/login')
.get(defaultController.login)
.post(passport.authenticate('local', {
successRedirect: '/admin',
failureRedirect: '/login',
failureFlash: true,
successFlash: true,
session:true,
}), defaultController.loginPost);
And this is what I would like to apply, but it seems it won't work and stuck in a infinite loading on chrome, however on console, it can receive an output:
here’s the output from the console
router.route('/login')
.get(defaultController.login)
.post(passport.authenticate('local', {
// successRedirect: '/admin',
failureRedirect: '/login',
failureFlash: true,
successFlash: true,
session:true,
}), (user)=>{
console.log(user.user.role);
if(user.user.role === 'admin'){
defaultController.loginPost;
}else{
console.log('hi');
}
});
As additional information, here is snippets defaultController that is responsible for handling the request:
login: (req,res)=>{
console.log();
res.render('default/login')
},
loginPost: (req,res)=>{
console.log(req.body.username);
res.render('/admin')
},
Any help?
you should use redirect instead of render so do like this:
login: (req,res)=>{
console.log();
res.redirect('default/login')
},
loginPost: (req,res)=>{
console.log(req.body.username);
res.redirect('/admin')
},
Assuming I have required passport, bcrypt, express-sessions and mysql correctly this code is supposed to add the user info to the session. I cannot for the life of me work out where it is going wrong.
App.js file
passport.use('local', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true //passback entire req to call back
}, function(req, email, password, done) {
connection.query("SELECT * FROM accounts WHERE email = ?", [email], async(err, rows, fields) => {
//if an error occurrs in mysql
if (err) {
return done(null, false)
connection.end()
}
//if there are no matching entries
if (!rows.length) {
console.log('invalid email')
return done(null, false)
connection.end()
}
//if the passwords don't compare
if (!(await bcrypt.compare(password, rows[0].password))) {
console.log('incorrect password')
done(null, false)
connection.end()
}
//if none of that happens
req.session.user = rows[0]
console.log('logged in')
connection.end()
});
}));
//handles de/serialization of the user data (all integrated from passport docs)
passport.serializeUser(function(user, done) {
return done(null, user.id)
console.log(user.id + "serialized")
});
passport.deserializeUser(function(id, done) {
connection.query("SELECT * FROM accounts WHERE id = " + id, function(err, rows) {
console.log('done' + rows[0])
return done(err, rows[0])
});
});
Auth route code
router.post('/auth', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/account'
}));
The code logs the user in, which is logged in the console, then logs them out again with a failure redirect to /account. I don't know where the authentication is going wrong, thanks for any replies in advance!
You can achieve the same using express-session..
install express-session: npm i express-session --save
Require it in your node application: var session = require('express-session');
Configure: app.use(session({ secret: "YourSecretKeyGoesHere", saveUninitialized: true, resave: true }));
And then check your session..
I have made a small login application using Express and Passport. But it seems I can't direct the user into a specific userprofile. What has to happen is, the user fills up an HTML form, and he has to get redirected to his own profile page (For the sake of simplicity, lets say that page differs from other user pages only in terms of the title). I have this in my user routes. (i.e. routes/users.js)
router.get('/userprofile', authenticationMiddleware(), function (req,
res, next) {
res.render('userprofile');
});
router.post('/login', passport.authenticate('local-login', {
successRedirect: '/users/userprofile',
failureRedirect: '/users/login',
failureFlash: true
}));
In my passport.js config file I have this.
passport.use('local-login', new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true
}, function (req, username, password, done) {
db.pool.getConnection(function (err, connection) {
if(err) throw err;
var query = connection.query('SELECT * from users WHERE username = ?', username, function (err, rows) {
if(err) return done(err);
if(!rows.length) {
return done(null, false, req.flash('loginMessage', 'No User Found'));
}
//Comparing passwords using bcrypt
bcrypt.compare(password, rows[0].password, function(error, res){
if(res){
return done(null, rows[0]);
} else {
return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.'));
}
});
});
});
}));
What I need to do is get the username from the form, and pass it to the successRedirect attribute in passport.authenticate, and then I can modify the get method adding a route parameter like '/users/:username' and render 'username' view.
How can I do this?
EDIT:
I did something like this.
router.get('/userprofile/:username', authenticationMiddleware(), function (req, res, next) {
res.render('userprofile', {
username: req.params.username,
title: 'Welcome, '+ req.params.username
});
});
router.post('/login', function (req, res, next) { //Testing callback.
console.log("Username is: " + req.body.username);
passport.authenticate('local-login', {
successRedirect: '/users/userprofile/' + req.body.username,
failureRedirect: '/users/login',
failureFlash: true
})(req, res);
next();
});
This works on some attempts. However, it returns this error sometimes.
POST /users/login 404 43.741 ms - 5226 /home/dasun/WebstormProjects/schoolentry/node_modules/passport/lib/middleware/authenticate.js:249
if (err) { return next(err)};
How can I get rid of this error?
Thanks.
Found the answer. I have missed next in POST method in /login route.
i.e. I should write
router.post('/login', function (req, res, next) { //Testing callback.
console.log("Username is: " + req.body.username);
passport.authenticate('local-login', {
successRedirect: '/users/userprofile/' + req.body.username,
failureRedirect: '/users/login',
failureFlash: true
})(req, res, next);
});
I build an application using Passport lib using this tutorial (part of it).
Note, I don't need a registration, only login form.
One of the issues is that my LocalStrategy callback is never called. For storing I use mongo:
mongoose.connect(dbConfig.url, {
useMongoClient: true
});
//dbConfig
module.exports = {
'url' : 'mongodb://localhost/passport'
}
Login route looks like this:
module.exports = function(app, passport) {
app.get('/login', function(req, res) {
res.render('login', {
message: req.flash('loginMessage')
});
});
app.post('/login', passport.authenticate('login', {
successRedirect: '/', // redirect to the secure profile section
failureRedirect: '/login', // redirect back to the signup page if there is an error
failureFlash: true // allow flash messages
}));
}
Passport logic is:
module.exports = function(passport) {
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use('login', new LocalStrategy({
passReqToCallback: true
}, function(req, username, password, done) {
console.log('start'); // never called
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);
});
}));
};
console.log('start'); is never called, although passport.authenticate('login' ...) is called.
What can be an issue?
I finally fixed it and everything works. In case anyone face the same issues I'm posting here several problems and solutions.
The req.body was empty in my app.post, because I didn't add body parser. Fixed it with:
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
Username field was empty all the time because I named it as email and passport expected username. Fixed with:
new LocalStrategy({
usernameField: 'email', // this parameter
passReqToCallback: true
}