Johnny
Johnny

Reputation: 51

ldapjs handling client.search response

I have the below code which is binding to an LDAP server and I want to return the user that I have added "ab" within the "interviewees" group (code taken from ldapjs client api page). I can see I am getting back a response from the server with the expected EventEmitter object. I am expecting to see information about the user when calling logging console.log() on the searchEntry object. I appear to have no searchEntry objects. Is my DN for my user correct? I am currently unsure whether the issue is with my query and I am not getting any data back or whether I am failing to process the response correctly?

    const client = ldap.createClient({ url: 'ldap://' + LDAP_SERVER + ':' + LDAP_PORT });
    
    // Connect and bind to the Active Directory.
    const connectToClient = async () => {
      const secret = LDAP_SECRET_KEY;
      return await new Promise((resolve, reject) => {
        client.bind(LDAP_USER, secret, function (err, res) {
          if (err) {
            console.error(err);
            reject('Failed to connect to LDAP server');
          } else {
            resolve('Connected to LDAP server');
          }
        });
      });
    };
    
    onst searchADForUser = async () => {
      return await new Promise((resolve, reject) => {
        client.search('CN=ab,OU=interviewees,OU=Users,OU=interview,DC=interview,DC=workspace,DC=com', function (err, res) {
          if (err) {
            console.error(err);
            reject('Error searching LDAP server');
          } else {
            res.on('searchEntry', function (entry) {
              console.log('entry: ' + JSON.stringify(entry.object));
            });
            res.on('searchReference', function (referral) {
              console.log('referral: ' + referral.uris.join());
            });
            res.on('error', function (err) {
              console.error('error: ' + err.message);
            });
            res.on('end', function (result) {
              console.log('status: ' + result.status);
            });
            resolve(res);
          }
        });
      });
    };
    
    const handler = async (event) => {
      try {
        return responses.success(
          await connectToClient().then(async function(event) {
            console.log(event);
            await searchADForUser().then(function(event) {
              console.log(event);
            }).catch(function(event) {
              console.log(event);
            })
          }).catch(function(event) {
            console.log(event);
          })
        );
      } catch (err) {
        console.error(err);
        return responses.error(err);
      } finally {
        client.unbind();
      }
    };

The active directory structure is below

enter image description here

Upvotes: 1

Views: 1143

Answers (1)

Johnny
Johnny

Reputation: 51

The central issue I was having was understanding how to process the returned EventEmitter object from the search function. I need to add to an array on each searchEntry event and then return that entry in my resolve callback function only once the end event had occurred. The code above was calling resolve immediately and hence no searchEntry events or the end event had been processed yet.

Code I am now using below:

function (err, res) {
        if (err) {
          console.error(err);
          reject(new Error('Error retrieving users from Active Directory'));
        } else {
          const entries = [];
          res.on('searchEntry', function (entry) {
            entries.push(entry);
          });
          res.on('searchReference', function (referral) {
            console.log('referral: ' + referral.uris.join());
          });
          res.on('error', function (err) {
            console.error('error: ' + err.message);
          });
          res.on('end', function (result) {
            console.log('status: ' + result.status);
            if (result.status !== 0) {
              reject(new Error('Error code received from Active Directory'));
            } else {
              resolve(entries);
            }
          });
        }
      }

Upvotes: 1

Related Questions