How can I report an invalid login correctly using Express and PassportJS?

I have successfully applied passport-local in my Express / Mongoose web app, but I am having trouble figuring out how to display the failed login message correctly.

Here's my login:

app.get('/login', function(req, res) {
   res.render('user/login', {
   });
});

      

With a route like this, how am I supposed to report an invalid login? If the login succeeds, it will write id

/ username

to the object req.user

, but that doesn't help me in the route "GET /login"

, because if it succeeds, you will get a redirect to the page you want to submit.

This means it req.user

will always be undefined

when you GET

login page.

I want to be able to write a message that says "yo, invalid login!" when the following events occur:

  • The user does not exist.
  • The provided password does not match, but the user exists.

I may need to display a different message depending on what happened.

When I implemented LocalStrategy I used this code:

passport.use(new LocalStrategy({
    usernameField: 'email'
},
function(email, password, fn) {
  User.findOne({'login.email': email}, function(err, user) {
    // Error was thrown.
    if (err) {
      return fn(err);
    }

    // User does not exist.
    if (!user) {
      return fn(null, false);
    }

    // Passwords do not match.
    if (user.login.password != utility.encryptString(user.login.salt + password)) {
      return fn(null, false);
    }

    // Everything is good.
    return fn(null, user);
  });
}
));

      

As you can see there are some issues, but this is how the author of PassportJS installed his application. How are we supposed to access what the Strategy will return?

As if it was throwing an error that I should even call to access err

?

Thank.

+3


source to share


2 answers


You can use a custom callback function or middleware to have more control. See the Authentication section in the manual for examples.

For example, a custom callback might look like this:

app.get('/login', function(req,res,next) {
    passport.authenticate('local', function(err,user) {
            if(!user) res.send('Sorry, you\'re not logged in correctly.');
            if(user) res.send('Skeet skeet!');
    })(req,res,next);
});

      

Alternatively, you can always redirect both responses:



app.get('/login', 
    passport.authenticate('local', { successRedirect: '/winner',
                                     failureRedirect:'/loser' }));

      

Or to redirect the failure with simple middleware:

app.get('/login', ensureAuthenticated,
    function(req,res) {
                // successful auth
                // do something for-the-win
    }
);

    // reusable middleware
    function ensureAuthenticated(req,res,next) {
        if(req.isAuthenticated()) {return next();}
        res.redirect('/login/again'); // if failed...
    }

      

+10


source


In the latest version of Passport, I have added support for flash messages to make it easier to fulfill your requests.

You can now provide a third argument done

, which may contain the error message. For example:

if (user.login.password != utility.encryptString(user.login.salt + password)) {
  return fn(null, false, { message: 'yo, invalid login!' });
}

      

Then set failureFlash

as true

as an option authenticate()

.

passport.authenticate('local', { successRedirect: '/',
                                 failureRedirect: '/login',
                                 failureFlash: true });

      



In this case, if authentication fails, the message will be set in a flash, ready to be rendered when the login page is redisplayed.

Custom callbacks are great too. The built-in options just make common tasks easier.

Also, I'm wondering: you mention that there are problems with the sample. What do you think needs to be improved? I want to give examples as best I can. Thank!

(For more details see comment on question # 12).

+17


source







All Articles