node.js - Node JS LDAP Auth User

node.js – Node JS LDAP Auth User

node.js – Node JS LDAP Auth User

In this case, you need ldapClient rather than ldapServer, this is the example code from the official doc:

var ldap = require(ldapjs);

ldap.Attribute.settings.guid_format = ldap.GUID_FORMAT_B;

var client = ldap.createClient({
  url: ldap://127.0.0.1/CN=test,OU=Development,DC=Home
});

var opts = {
  filter: (objectclass=user),
  scope: sub,
  attributes: [objectGUID]
};

client.bind(username, password, function (err) {
  client.search(CN=test,OU=Development,DC=Home, opts, function (err, search) {
    search.on(searchEntry, function (entry) {
      var user = entry.object;
      console.log(user.objectGUID);
    });
  });
});

@Sukh Thank you for posting your UPDATE solution; however, there is a problem with the code you posted in your UPDATE. While it works for simple cases, with larger queries, you will find you are unbinding before the results have been output. The solution for me was to move your unbinds into the search.on functions.

Here is an edit of your UPDATE:

var ldap = require(ldapjs);
ldap.Attribute.settings.guid_format = ldap.GUID_FORMAT_B;
var client = ldap.createClient({
      url: ldap://batman.com/cn=+username+, ou=users, ou=compton, dc=batman, dc=com,
      timeout: 5000,
      connectTimeout: 10000
});
var opts = {
  filter: (&(objectclass=user)(samaccountname=+username+)),
  scope: sub,
  //attributes: [objectGUID]
  // This attribute list is what broke your solution
  attributes: [objectGUID,sAMAccountName,cn,mail,manager,memberOf]
};

console.log(--- going to try to connect user ---);

try {
    client.bind(username, password, function (error) {
        if(error){
            console.log(error.message);
            client.unbind(function(error) {if(error){console.log(error.message);} else{console.log(client disconnected);}});
        } else {
            console.log(connected);
            client.search(ou=users, ou=compton, dc=batman, dc=com, opts, function(error, search) {
                console.log(Searching.....);

                search.on(searchEntry, function(entry) {
                    if(entry.object){
                        console.log(entry: %j  + JSON.stringify(entry.object));
                    }
                    client.unbind(function(error) {if(error){console.log(error.message);} else{console.log(client disconnected);}});
                });

                search.on(error, function(error) {
                    console.error(error:  + error.message);
                    client.unbind(function(error) {if(error){console.log(error.message);} else{console.log(client disconnected);}});
                });

                // dont do this here
                //client.unbind(function(error) {if(error){console.log(error.message);} else{console.log(client disconnected);}});
            });
        }
    });
} catch(error){
    console.log(error);
    client.unbind(function(error) {if(error){console.log(error.message);} else{console.log(client disconnected);}});
}

At least this is what I discovered when using your solution with Active Directory searches. memberOf returns A LOT of entries in my use case and the unbinds were being done prematurely, so I was getting the following error:

error: 1__ldap://my.domain.com/,OU=Employees,OU=Accounts,DC=my,DC=domain,DC=com closed
client disconnected

node.js – Node JS LDAP Auth User

Suggestions

1.Dont use ldapauth-fork (Huge hanging issue, if we hit multiple requests then after some time library gets unresponsive and doesnt return anything.)

2.Dont use passport-ldapauth (Internally calls ldapauth-fork)

We can use ldapjs, which has easy implementation and is based on event driven approach.

Below nodejs code explain complete solution for ldap auth and search.

JS code

const ldap = require(ldapjs);
let client

// unbind after completion of process
function closeConnection() {
    console.log(closeConnection)
    client.unbind(err => {
        console.log(unbind error, err)
    });
}

function search() {
    const searchOptions = {
        filter: (uid=yourSearchText), // search text
        scope: sub
    };
    return new Promise((resolve, reject) => {
        client.search(ou=consultants, + ou=Your OU,ou=yourOu,dc=yourDc,dc=com, searchOptions, (err, res) => {
            res.on(searchEntry, entry => {
                console.log(searchEntry, entry.object);
                resolve(entry.object)
            });
            res.on(searchReference, referral => {
                console.log(referral:  + referral.uris.join());
                resolve(referral.uris.join())
            });
            res.on(error, err => {
                console.error(search error:  + err.message);
                reject(err)
            });
            res.on(end, result => {
                console.log(If not found, result);
                reject({ message:User not found})
            });
        });
    })
}

function authenticate() {
    const server = ldap server ip;
    client = ldap.createClient({
        url: `ldap://${server}`
    });

    return new Promise((resolve, reject) => {
        client.bind(cn=yourcn,dc=yourdc,dc=com, sortedSolutions, err => {
            if (err) {
                reject(err)
            }
            resolve(Authenticated successfully)
        });
    })
}

function start(req, res) {
    let searchResponseData
    authenticate()
        .then(authenticateResponse => {
            console.log(authenticateResponse, authenticateResponse)
            return search()
        })
        .then(searchResponse => {
            console.log(searchResponsesearchResponse, searchResponse)
            searchResponseData = searchResponse
            return closeConnection()
        })
        .then(closeConnectionResponse => {
            console.log(ldap connection closed, closeConnectionResponse)
            res.status(200).send(searchResponseData)
        })
        .catch(error => {
            console.log(catch error, error)
            res.status(400).send(error)
        })

}

module.exports.start = start

// We can use same code with no authentication, Just pass to bind function client.bind(, , err => { //same as above })

Related posts on Node js  :

Leave a Reply

Your email address will not be published.