简体   繁体   中英

Passport.js fails on req.login

I have configured passport.js within sails.js and I am using passport-ldapauth for authentication.

I believe I have configured it properly, I am returned an some parameters from LDAP regarding the user, however it appears that passport.js dies when I attempt to req.logIn.

Here is part of the AuthController:

process: function (req, res) {
    passport.authenticate('ldapauth', {session: true}, function(err, user, info) {
      console.log("Authenticated?", err, user, info);

      if ((err) || (!user)) {
        res.redirect('/login');
        return;
      }

      req.logIn(user, function (err) {
        if (err) {
          console.log(err);
          res.view();
          return;
        }
        res.redirect('/');
        return;
      });
    })(req, res);
  },

Here is the passport stategeies and serialize user function:

function findByEmployeeID(u, fn) {
  User.findOne({
    employeeID: u
  }).done(function (err, user) {
    // Error handling
    if (err) {
      return fn(null, null);
      // The User was found successfully!
    } else {
      return fn(null, user);
    }
  });
}

passport.serializeUser(function (user, done) {
  console.log("Serialize User", user.id);
  done(null, user.id);
});

passport.deserializeUser(function (id, done) {
  findById(id, function (err, user) {
    console.log("Deserialize User: ", id, user.id);
    done(err, user);
  });
});

passport.use(new LDAPStrategy({
    server: {
      url: 'ldap://server.domain.com:389',
      adminDn: '<ADMIN BIND DN>',
      adminPassword: '<ADMIN BIND PW>',
      searchBase: '<BASEDN>',
      searchFilter: '(&(objectClass=person)(sAMAccountName={{username}}))',
      searchAttributes: ['sAMAccountName', 'employeeID', 'mail', 'displayName', 'givenName', 'sn', 'telephoneNumber','mobile'],
    }
  }, function (user, done) {
    // Will always have an authenticated user if we get here since passport will indicate the failure upstream.

    console.log("LDAP User", user.employeeID); //This returns the proper users EmployeeID.

    //Map the LDAP user to our local mapping
    var mapUser = ldapUserMapping(user);

    //Check to see if the user exists in the local database
    findByEmployeeID(mapUser.employeeID, function (err, localUser) {
      if (err) done(err, null, err);
      if (!localUser) {
        //This must be a new user who authenticated via LDAP, create a local user account.
        User.create(mapUser).done(function(err, localUser){
          if (err) done(err, null, err);
          return done(null, localUser);
        });
      } else {
        //This is a user who has accessed our system before

        //Maybe update the user settings if upstream LDAP has updated anything.

        //Return User
        return done(null, localUser);
      }
    });
  }
));

Req.login debug:

req.login =
req.logIn = function(user, options, done) {
  if (typeof options == 'function') {
    done = options;
    options = {};
  }
  options = options || {};

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

  this[property] = user;
  if (session) {
    if (!this._passport) { throw new Error('passport.initialize() middleware not in use'); }
    if (typeof done != 'function') { throw new Error('req#login requires a callback function'); }

    var self = this;
    console.log("req.login about to call passport serializeUser");
    this._passport.instance.serializeUser(user, this, function(err, obj) {
    console.log("Did this return?", err, obj);
      if (err) { self[property] = null; return done(err); }
      self._passport.session.user = obj;
      done();
    });
  } else {
    done && done();
  }
};

Passport Serializer Debug:

Passport.prototype.serializeUser = function(fn, done) {
  if (typeof fn === 'function') {
    return this._serializers.push(fn);
  }

  // private implementation that traverses the chain of serializers, attempting
  // to serialize a user
  var user = fn;

  var stack = this._serializers;
  (function pass(i, err, obj) {
    console.log("Beginning pass with: ", i, err, obj);
    // serializers use 'pass' as an error to skip processing
    if ('pass' === err) {
      err = undefined;
    }
    // an error or serialized object was obtained, done
    if (err || obj || obj === 0) {
      console.log("ERROR Or OBJ obtained:", i, err, obj);
      return done(err, obj);
    }

    var layer = stack[i];
    if (!layer) {
      console.log("This failed to serialize?", i);
      return done(new Error('failed to serialize user into session'));
    }

    try {
      layer(user, function(e, o) {
        console.log("From serialize function", i, e, o);
        pass(i + 1, e, o);
        console.log("After Pass?: ", i, e, o);
      } )
    } catch(e) {
      console.log("On catch: ", i, e);
      return done(e);
    }
  })(0);
}

Here is updated output:

LDAP User abc123
Authenticated? null { username: 'abc123',
  employeeID: 'abc123',
  email: 'First_Last@domain.com',
  firstName: 'First',
  lastName: 'Last',
  createdAt: Wed Apr 30 2014 17:09:21 GMT-0400 (EDT),
  updatedAt: Wed Apr 30 2014 17:09:21 GMT-0400 (EDT),
  id: '53616681156b068d3b38f8cb' } undefined
req.login about to call passport serializeUser
Beginning pass with:  0 undefined undefined
Serialize User 53616681156b068d3b38f8cb
From serialize function 0 null 53616681156b068d3b38f8cb
Beginning pass with:  1 null 53616681156b068d3b38f8cb
ERROR Or OBJ obtained: 1 null 53616681156b068d3b38f8cb
On catch:  0 [TypeError: object is not a function]
debug: Lowering sails...


~/project/node_modules/sails-mongo/node_modules/mongodb/lib/mongodb/connection/base.js:245
        throw message;
              ^
TypeError: object is not a function
    at pass (~/project/node_modules/passport/lib/passport/index.js:293:14)
    at Passport.serializeUser (~/project/node_modules/passport/lib/passport/index.js:295:5)
    at IncomingMessage.req.login.req.logIn (~/project/node_modules/passport-ldapauth/node_modules/passport/lib/http/request.js:51:29)
    at ~/project/api/controllers/AuthController.js:34:11

It seems that is unable to serialize the user, though I'm not exactly sure why. The SerializeUser should be passing the user.id value though it doesnt seem be working from within passport.js. Maybe I have something configured improperly?

Have you done this first step when setting up passport?

Before authenticating requests, the strategy (or strategies) used by an application must be configured.

passport.use(new LocalStrategy(
  function(username, password, done) {
    User.findOne({ username: username, password: password }, function (err, user) {
      done(err, user);
    });
  }
));

The layer code that is being called is supposed to be walking through the registered serializeUser functions and calling them ( lib/authenticator.js line 275ish). Your debug logging is suggesting that there isn't a function on in that array. You look to be registering the serializeUser callback correctly, which is why i'm leaning towards an initialization problem.

I'm not sure why the this object is being passed into serializeUser as the 2nd argument, but it seems that is the problem.

this._passport.instance.serializeUser(user, function(err, obj) {
//this._passport.instance.serializeUser(user, this, function(err, obj) {

Making those changes in the ~/project/node_modules/passport-ldapauth/node_modules/passport/lib/http/request.js file seems to resolve the issue.

I'm not sure exactly why this occurs from installing the ldapauth module. I will investigate further.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM