YarGnawh
YarGnawh

Reputation: 4654

PassportJS - Custom Callback and set Session to false

Is it possible to use custom callback and disable session? In the documentation it shows how to disable session and custom callbacks, but how do i combine them?

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) {

      // I'm getting an error here
      // [Error: Failed to serialize user into session]

      if (err) { return next(err); }
      return res.redirect('/users/' + user.username);
    });
  })(req, res, next);
});

Upvotes: 10

Views: 8148

Answers (2)

marekozw
marekozw

Reputation: 356

Please make sure you use newest version of passport (which is 0.2.1 for today).

Please try passing { session: false } as a second parameter of your req.logIn() function:

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, { session: false }, function (err) {

      // Should not cause any errors

      if (err) { return next(err); }
      return res.redirect('/users/' + user.username);
    });
  })(req, res, next);
});

Reason:

At first glance, passing { session: false } in passport.authenticate() seems to be reasonable because sourcecode of this method looks like:

Authenticator.prototype.authenticate = function(strategy, options, callback) {
  return this._framework.authenticate(this, strategy, options, callback);
};

So it should be able to honor second parameter. But if you start to drill down the function call stack, you realize that session attribute of options parameter is being disregarded completely. I mean, there is no reference to options.session inside

this._framework.authenticate(this, strategy, options, callback);

function.

So basically you want to pass it in req.logIn() function. Source code of this function is as follows:

req.logIn = function(user, options, done) {
  if (!this._passport) throw new Error('passport.initialize() middleware not in use');

  if (!done && typeof options === 'function') {
    done = options;
    options = {};
  }
  options = options || {};
  var property = this._passport.instance._userProperty || 'user';
  var session = (options.session === undefined) ? true : options.session;

  this[property] = user;
  if (session) { // HERE! It will not try to serialize anything if you pass {session: false}
    var self = this;
    this._passport.instance.serializeUser(user, function(err, obj) {
      if (err) { self[property] = null; return done(err); }
      self._passport.session.user = obj;
      done();
    });
  } else {
    done && done();
  }
}

P.S. Please consider installing your npm dependencies using npm install [package-name] --save instead of creating package.json manually. npm will automatically fetch newest stable version.

Upvotes: 21

Waldo Jeffers
Waldo Jeffers

Reputation: 2279

Have you tried directly combining them ? Something like :

passport.authenticate('local', { "session": false }, function(err,user,info){
   //blablabla
});

From passport's source code, authenticate is defined as follows :

Authenticator.prototype.authenticate = function(strategy, options, callback) {

So I don't see why you wouldn't be able to use both parameters.

Upvotes: 4

Related Questions