Can you authenticate with Passport without redirecting?

14.7k Views Asked by At

I have the following working code to authenticate through the passport-local strategy:

  app.post('/api/login', passport.authenticate('local-login', {
    successRedirect : '/api/login/success',
    failureRedirect : '/api/login/error',
    failureFlash : true
  }));
  app.get('/api/login/error', function(req, res) {
    res.send(401, {error: req.flash('loginMessage')});
  });
  app.get('/api/login/success', function(req, res) {
    res.send(200, {user: req.user});
  });

However, ideally I want to handle the errors and success messages from one express route, and not redirect to two extra routes.

Is this possible? I tried using a 'custom callback' but that seemed to error out on serializing users for some reason.

2

There are 2 best solutions below

2
On BEST ANSWER

You can use custom callback, such as:

passport.authenticate('local', function (err, account) {
    req.logIn(account, function() {
        res.status(err ? 500 : 200).send(err ? err : account);
    });
})(this.req, this.res, this.next);

In err object you can find all needed errors, which was appeared at authentication.

3
On

Are you using Mongoose? Try adding this to your server.js/index.js

var User = mongoose.model('User');
passport.use(new LocalStrategy(User.authenticate()));
passport.use(User.createStrategy());
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());

This to your routes index.js

var auth = require('./auth');
app.post('/api/auth/login', passport.authenticate('local'),auth.login);

auth.js:

var UserModel = require('../models/user');
var User = new UserModel();

exports.login = function(req, res) {
    var user = req.user;
    req.login(user, function(err) {
        //if error: do something
        return res.status(200).json(user)
    });
};

Add this to model index.js

var passportLocalMongoose = require('passport-local-mongoose');
userSchema.plugin(passportLocalMongoose, {
    usernameField: 'email',
    usernameLowerCase: 'true'
});

I'm making a lot of assumptions on structure and packages here. but this should work

EDIT

For custom callbacks:

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);
});

Here you instead of res.redirect you can use something like return res.status(404).json("Not Found)

See docs for more information : http://passportjs.org/guide/authenticate/