I have Passport Local working on my app.
Success brings authenticates and failure does not.
However im trying to make it fail better through fail messages and escaping the action.
Tried following the passport documentation.
The error messages are not appearing for some reason, would appreciate some assistance!
here is the local startegy
// Configure the local strategy for use by Passport.
passport.use(new Strategy(
function(username, password, cb) {
db.users.findByUsername(username, function(err, user) {
if (err) { return cb(err); }
if (!user) { return cb(null, false,req.flash('message','Invalid username or password')); }
if (user.password != password) { return cb(null, false,req.flash('message','Invalid username or password')); }
return cb(null, user);
});
}));
The authentication
//Home
app.post('/home.ejs',
passport.authenticate('local'),
function(req, res) {
res.redirect('/');
});
I also have another attempt at authentication if this is more accurate but also had no luck
//Home
app.post('/home.ejs', function( req, res, next) { passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); req.flash('message','Invalid username or password') }
if (!user) { return res.redirect('/'); failureFlash: 'Invalid username or password' }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/');
});
})(req, res, next);
});*/
It should be
passport.use(new LocalStrategy ...
instead of your
passport.use(new Strategy(.....
Related
I am implementing auth using passport js and database is mysql. My successRedirect route is '/main' and in the main route, I have added a middleware (isAuthenticated). But the issue is that, after entering valid credentials, I am not being redirected to '/main', instead, it just timeouts. I tried without adding middleware to '/main' route and it works fine.
var isAuthenticated = function(req, res, next) {
if (req.isAuthenticated()) {
return next;
}
res.redirect("/login")
}
// AUTH Implementation
app.use(session( {
secret: "asdnoifjasofijmaofmjkneknf",
resave: false,
saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
passport.use(new localStrategy(
function(username, password, done) {
connection.query("SELECT password FROM user" +
" WHERE email = ?", [username], function (err, results, fields) {
if (err) {
console.log(err);
}
else if (results.length === 0) {
done(null, false);
}
else {
console.log("Results");
console.log(results[0]);
hashedPassword = results[0].password;
bcrypt.compare(password, hashedPassword, function (err, response) {
if (response) {
console.log("True");
return done(null, true);
}
else {
console.log("False");
return done(null, false);
}
})
}
})
}
));
passport.serializeUser(function(ID, done) {
done(null, ID);
});
passport.deserializeUser(function(ID, done) {
connection.query("SELECT * FROM user WHERE userID = ?", [ID], function (err, results, fields) {
if (err) throw err;
else if (results.length === 0) done(null, false);
else {
done(null, results[0]);
}
})
done(null, ID);
});
app.post("/login", passport.authenticate('local', {
successRedirect: "/main",
failureRedirect: "/login"
}))
app.get("/main", isAuthenticated, function(req, res) {
res.send("In the main page");
})
app.post("/login", passport.authenticate('local', {
successRedirect: "/main",
failureRedirect: "/login"
}))
Help me out.
You need execute next function instead of return it.
var isAuthenticated = function(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect("/login")
}
Last time I used passport authenticate for login in the following manner:
router.post('/login', parserUrlEncodedTrue, (request, res, next) => {
console.log('logging in user');
passport.authenticate('local', (err, user, info) => {
var options = "";
if(err){
return next(err);
}
if(!user){
return res.json({
error: true,
message: "User doesn't exist"
});
}
req.logIn(user, function(err) {
if (err){
return next(err);
}
return res.json({
error: false,
message: "Login Success"
});
});
})(req, res, next);
Now I'm trying to use formidable.js and it works fine for registration but can't make it work with login.
let form = new formidable.IncomingForm();
form.parse(req, (err, fields, files) => {
if(err){
helpers.errors(err, res);
} else {
passport.authenticate('local', (err, user, info) => {})(req, res, next);
}
});
passport.authenticate gets to req before it is parsed by formidable. I'm also using express and passport-local-mongoose.
I'm experimenting with Passportjs and the code for a Custom Callback is:
app.get('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/users/' + user.username);
});
})(req, res, next);
});
I'm happy with all of this code except for the second to last line (req, res, next); - Could someone explain why these parameters are added on the end. This is probably more of a JS question than a Passport question but any help is much appreciated.
The "javascript" answer is that it returns a function which is called again with those 2nd set of arguments.
That function is the "accumulator for failures from each strategy in the chain".
https://github.com/jaredhanson/passport/blob/master/lib/middleware/authenticate.js
You can rewrite it without the anonymous function, or the custom callback. Just use passport's passport.use(new LocalStrategy()) function to create the new strategy. See 'Configure' docs.
passport.use(new LocalStrategy(
function(username, password, done) {
logIn({ 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);
});
}
));
The only change you need to make is move the logIn function to be in this file, and not a method to req. Then you can simply call passport.authenticate like so:
app.get('/login', passport.authenticate('local', { successRedirect: '/',
failureRedirect: '/login' }));
So instead of using res.redirect in the callback, you just use passport's built in successRedirect and failureRedirect properties. You can see their docs as well, on the authentication page.
Connect/Express middleware function has signature:
function(req, res, next)
passport.authenticate() can be used as a middleware, e.g:
app.post('/login', passport.authenticate('local'), nextMiddleware);
This means authenticate() returns a middleware function object, which you can evoke with (req, res, next) parameters to continue the app's request-response cycle.
I am new to node.js in general and passport in particular.
I have exposed a passport configuration in a file by itself like the following:
var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/User');
var messages = {
100: 'Username and/or password are not correct.',
101: 'User already exists.'
};
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('local-login', new LocalStrategy(function (username, password, done) {
User.findOne({ username: username }, function (err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, req.flash('loginMessage', messages['100']));
}
user.comparePassword(password, function (err, isMatch) {
if (err) {
return done(err);
}
if (isMatch) {
return done(null, user);
} else {
return done(null, false, req.flash('loginMessage', messages['100']));
}
});
});
}));}
in my node routes, i am doing the following to handle the login scenario:
app.post('/login',function(req, res, next){
console.log('loggin in ')
passport.authenticate('local-login', function(err, user, info){
console.log('allo');
console.log(err);
console.log(user);
console.log(info)
});
});
however I am not getting a response; can you please clarify what I am doing wrong.
You need to return the object returned by passport.authenticate
app.post('/login',function(req, res, next){
console.log('loggin in ')
/**/return passport.authenticate('local-login', function(err, user, info){
console.log('allo');
console.log(err);
console.log(user);
console.log(info)
})(req, res, next);
});
I am using passportjs for user authentication. In the official guide, the only shown user case is a redirection operation after authentication:
app.post('/login',
passport.authenticate('local', { successRedirect: '/',
failureRedirect: '/login',
failureFlash: true })
);
However, in my application, I don't want passport to redirect immediately. Instead, I hope passport could send me back some json object indicating whether the authentication is success or not. How I can do that?
You can send custom responses -
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.send(400, 'Incorrect username');
}
req.logIn(user, function(err) {
if (err) {
return next(err);
}
res.send({'message': 'User authenticated'});
});
})(req, res, next);
});