As per the documentation, if I was handle authentication requests like so, I would be able to capture successful attempts.
app.post('/login',
passport.authenticate('local'),
function(req, res) {
// If this function gets called, authentication was successful.
// `req.user` contains the authenticated user.
res.redirect('/users/' + req.user.username);
});
But, like the documentation says:
By default, if authentication fails, Passport will respond with a 401 Unauthorized status, and any additional route handlers will not be invoked. If authentication succeeds, the next handler will be invoked and the req.user property will be set to the authenticated user.
How can I handle the unauthorized login attempt?
I know I can handle it with custom middleware but is there a better way?
You should have a look at the Custom Callback section in passport docs which explains about how to override the built in behavior of handling an authentication request. You can write a custom callback which will serve as the done
function that you are invoking from the Strategy.
app.get('/login', function(req, res, next) {
/* look at the 2nd parameter to the below call */
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);
});
Look at the second parameter to the passport.authenticate
call, which will serve as the done
function that you invoke from the local strategy.
See the done
function invoked in the code below, which is the local strategy that you define for passport. You can call the done
function with various available parameters like err
, user
, info
set from the strategy according to the response from API call or db operation. These parameters will be processed by the above function definition in the passport.authenticate
call.
passport.use(new LocalStrategy(
function(username, password, done) {
/* see done being invoked with different paramters
according to different situations */
User.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.verifyPassword(password)) { return done(null, false); }
return done(null, user);
});
}
));