title: LDAP authentication using passport-ldapauth on Node.js
body: <p>I've been struggling with passport-ldapauth for a couple of days, and I have no more ideas left what am I doing wrong.</p>
  
  <p>Briefly, I have a project that uses two passport strategies: local and LDAP. Local strategy works perfectly for me, but LDAP is the problematic one.</p>
  
  <p>I have a read-only user for AD (let's call it "ldap-read-only-admin"), and I am able to connect with this user via external LDAP client and view the relevant OU. I have also triple-checked the SearchBase, and it seems to be correct.</p>
  
  <p>However, when passing the same configuration to passport-ldapauth, it seems that it cannot bind user credentials (I guess). Any ideas on how to debug this will be much appreciated.</p>
  
  <p>This is the app.js:</p>
  
  <pre><code>    var express = require("express");
      var app     = express();
      var path    = require("path");
      var session = require("express-session");
      var mongoose = require("mongoose");
      var passport = require("passport");
      var flash = require("connect-flash");
      var cookieParser = require("cookie-parser");
      var bodyParser = require("body-parser");
      var morgan = require("morgan");
  
      var configDB = require('./config/database.js');
      require('./config/passport.js')(passport); // pass passport for configuration
  
  
      app.use(express.static(__dirname + '/public'));  
  
      app.set('view engine', 'ejs');
  
      //connect to the Database
      var promise = mongoose.connect(configDB.url, {
        useMongoClient: true,
      });      
  
      app.use(morgan('dev')); // log every request to the console
      app.use(cookieParser()); // read cookies (needed for auth)
      //app.use(bodyParser()); // get information from html forms
      app.use(bodyParser.urlencoded({
        extended: true
      }));
      app.use(bodyParser.json({
        extended: true
      }));
  
      // configuring passport
      app.use(session({ secret: 'secret',  resave: true, saveUninitialized: true })); // session secret
      app.use(passport.initialize());
      app.use(passport.session()); // persistent login sessions
      app.use(flash()); // use connect-flash for flash messages stored in session
  
  
      require('./modules/routes.js')(app, passport); // load our routes and pass in our app and fully configured passport
  
  
      //make Web server listen on a specific port
      app.listen(3000);
  
      logger.info("Listening on port 3000");
  </code></pre>
  
  <p>This is routes.js (the relevant part):</p>
  
  <pre><code>module.exports = function(app, passport) {
  app.post('/', function(req, res, next) {
  
      passport.authenticate('ldap-login', {session: true}, function(err, user, info) {
      console.log("user: " + user);
      console.log("info: " + JSON.stringify(info));
        if (err) {
          return next(err); // will generate a 500 error
        }
        // Generate a JSON response reflecting authentication status
        if (! user) {
          return res.send({ success : false, message : 'authentication failed' });
        }
        return res.send({ success : true, message : 'authentication succeeded' });
      })(req, res, next);
    });
  
  
  }
  </code></pre>
  
  <p>And this is passport.js:</p>
  
  <pre><code>    var LocalStrategy   = require('passport-local').Strategy;
      var LdapStrategy    = require('passport-ldapauth').Strategy;
  
      // load the user model
      var User            = require('../modules/user.js');
  
      // expose this function to our app using module.exports
      module.exports = function(passport) {
  
          // =========================================================================
          // passport session setup ==================================================
          // =========================================================================
          // required for persistent login sessions
          // passport needs ability to serialize and unserialize users out of session
  
          // used to serialize the user for the session
          passport.serializeUser(function(user, done) {
              done(null, user.id);
          });
  
          // used to deserialize the user
          passport.deserializeUser(function(id, done) {
              User.findById(id, function(err, user) {
                  done(err, user);
              });
          });
  
  
        // =========================================================================
          // LOCAL LOGIN =============================================================
          // =========================================================================
  
          passport.use('local-login', new LocalStrategy({
  
             passReqToCallback : true // allows us to pass back the entire request to the callback
          },
          function(req, username, password, done) { // callback with email and password from our form
  
              // find a user whose email is the same as the forms email
              // we are checking to see if the user trying to login already exists
              User.findOne({ username :  username }, function(err, user) {
                  // if there are any errors, return the error before anything else
                  if (err)
                      return done(err);
  
                  // if no user is found, return the message
                  if (!user)
                      return done(null, false, req.flash('loginMessage', 'The username "' + username + '" is not found.')); // req.flash is the way to set flashdata using connect-flash
  
                  // if the user is found but the password is wrong
                  if (!user.validPassword(password))
                     return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.')); // create the loginMessage and save it to session as flashdata
  
                  // all is well, return successful user
                  return done(null, user);
              });
  
          }));
  
  
  
          // =========================================================================
          // LDAP Login ==============================================================
          // =========================================================================
  
          var opts = {
              server: {
                      url: 'ldap://&lt;ldap server address&gt;:389',
                      bindDn: 'cn=ldap-read-only-admin',
                      bindCredentials: 'password',
                      searchBase: 'OU=XX1, OU=XX2, DC=domain, DC=local',
                      searchFilter: '(uid={{username}})',    
                     // passReqToCallback : true
                    }
          };
  
        passport.use('ldap-login', new LdapStrategy(opts, function(req, user, done) {
              console.log("Passport LDAP authentication.");
            done(null, user);
          }
  
      ));   
  
      };
  </code></pre>