{"id":15677,"library":"ldapts","title":"LDAPts Client","description":"LDAPts is a modern, TypeScript-first LDAP client library for Node.js, providing a robust API to interact with LDAP directory servers, including Active Directory. It supports both `ldap://` and `ldaps://` protocols, offering comprehensive options for secure connections using TLS. The library is currently at version 8.1.7 and maintains an active release cadence, frequently publishing bug fixes and minor enhancements. Key features include client creation with configurable timeouts, strict DN parsing, and support for various LDAP operations such as bind, add, compare, delete, modify, and search. It differentiates itself by offering full TypeScript type definitions out-of-the-box, targeting recent Node.js versions (>=20), and internally handling BER encoding/decoding, reducing external dependencies.","status":"active","version":"8.1.7","language":"javascript","source_language":"en","source_url":"https://github.com/ldapts/ldapts","tags":["javascript","ldap","active","directory","typescript"],"install":[{"cmd":"npm install ldapts","lang":"bash","label":"npm"},{"cmd":"yarn add ldapts","lang":"bash","label":"yarn"},{"cmd":"pnpm add ldapts","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"LDAPts is an ESM-first package, requiring `import` syntax.","wrong":"const { Client } = require('ldapts')","symbol":"Client","correct":"import { Client } from 'ldapts'"},{"note":"Generic LDAP controls are imported from a subpath. Specific control implementations are also available.","wrong":"const { Control } = require('ldapts/controls')","symbol":"Control","correct":"import { Control } from 'ldapts/controls'"},{"note":"Commonly used controls like PagedResultsControl are directly available from the controls subpath.","wrong":"const { PagedResultsControl } = require('ldapts/controls')","symbol":"PagedResultsControl","correct":"import { PagedResultsControl } from 'ldapts/controls'"},{"note":"BerReader and BerWriter are now exported directly from the main package entry point since v8.1.4, useful for custom BER parsing/writing.","wrong":"const { BerReader } = require('ldapts')","symbol":"BerReader","correct":"import { BerReader } from 'ldapts'"},{"note":"This error class is exported for explicit handling of malformed ASN.1 data, available since v8.1.4.","wrong":"const { InvalidAsn1Error } = require('ldapts')","symbol":"InvalidAsn1Error","correct":"import { InvalidAsn1Error } from 'ldapts'"}],"quickstart":{"code":"import { Client } from 'ldapts';\n\nasync function connectAndSearch() {\n  const ldapUrl = process.env.LDAP_URL ?? 'ldap://localhost:389';\n  const bindDN = process.env.LDAP_BIND_DN ?? 'cn=admin,dc=example,dc=com';\n  const bindPassword = process.env.LDAP_BIND_PASSWORD ?? 'password';\n  const searchBase = process.env.LDAP_SEARCH_BASE ?? 'dc=example,dc=com';\n  const searchFilter = process.env.LDAP_SEARCH_FILTER ?? '(objectClass=*)';\n\n  const client = new Client({\n    url: ldapUrl,\n    timeout: 5000, // Milliseconds client should let operations live for\n    connectTimeout: 5000, // Milliseconds client should wait for TCP connection\n    tlsOptions: {\n      minVersion: 'TLSv1.2', // Enforce minimum TLS version\n      rejectUnauthorized: false // Set to true in production with valid certs\n    },\n    strictDN: true\n  });\n\n  try {\n    console.log(`Attempting to bind as ${bindDN} to ${ldapUrl}...`);\n    await client.bind(bindDN, bindPassword);\n    console.log('LDAP bind successful!');\n\n    console.log(`Performing search under '${searchBase}' with filter '${searchFilter}'...`);\n    const { searchEntries, searchReferences } = await client.search(\n      searchBase,\n      {\n        filter: searchFilter,\n        scope: 'sub',\n        attributes: ['dn', 'cn', 'mail'], // Request specific attributes\n        sizeLimit: 10 // Limit results for example\n      }\n    );\n\n    if (searchEntries.length > 0) {\n      console.log(`Found ${searchEntries.length} entries.`);\n      searchEntries.forEach(entry => {\n        console.log(`- DN: ${entry.dn}, CN: ${entry.cn ?? 'N/A'}, Mail: ${entry.mail ?? 'N/A'}`);\n      });\n    } else {\n      console.log('No entries found.');\n    }\n\n    console.log('Unbinding from LDAP server...');\n    await client.unbind();\n    console.log('Unbind successful.');\n\n  } catch (error: any) {\n    console.error('LDAP operation failed:', error.message);\n    // Specific error handling for common LDAP issues\n    if (error.code === 'ETIMEDOUT') {\n      console.error('Timeout occurred. Check network connectivity or server responsiveness.');\n    } else if (error.code === 'LDAP_INVALID_CREDENTIALS') {\n      console.error('Invalid credentials provided for bind operation.');\n    } else if (error.message.includes('ECONNREFUSED')) {\n      console.error('Connection refused. Ensure the LDAP server is running and accessible.');\n    }\n    process.exit(1);\n  } finally {\n    if (client.connected) {\n      await client.unbind().catch(e => console.error('Error during final unbind:', e.message));\n    }\n  }\n}\n\nconnectAndSearch();","lang":"typescript","description":"Demonstrates how to create an LDAPts client, bind to an LDAP server using credentials from environment variables, perform a basic search operation for entries, and then unbind gracefully. It includes basic error handling for common LDAP issues."},"warnings":[{"fix":"Upgrade your Node.js environment to version 20 or newer.","message":"LDAPts now strictly requires Node.js version 20 or higher. Older Node.js versions are not supported and may lead to runtime errors or installation issues.","severity":"breaking","affected_versions":"<8.0.0"},{"fix":"If experiencing issues with DN parsing, consider setting `strictDN: false` in the `Client` constructor options, but be aware of potential security implications or data inconsistencies.","message":"The `strictDN` option defaults to `true` in client configuration. This enforces strict DN parsing for client methods, which might cause issues if your application interacts with LDAP servers that return or expect less formally structured distinguished names.","severity":"gotcha","affected_versions":">=8.0.0"},{"fix":"If your application had relied on specific `asn1` internals exposed transitively through LDAPts, you will need to refactor to use LDAPts's own exported `BerReader` and `BerWriter` classes or handle ASN.1 parsing independently.","message":"The internal `asn1` package dependency has been replaced with an internal BER module since v8.1.1. While this improves maintainability and reduces external dependencies, direct reliance on `asn1` exports or specific behaviors from previous versions will no longer work.","severity":"breaking","affected_versions":">=8.1.1"},{"fix":"Configure `tlsOptions` explicitly with `minVersion: 'TLSv1.2'` (or higher) and `rejectUnauthorized: true`. Ensure your Node.js environment trusts the certificate authority that signed your LDAP server's certificate.","message":"The client configuration's `tlsOptions` should always specify a `minVersion` (e.g., 'TLSv1.2') and `rejectUnauthorized: true` in production environments for secure connections. Using outdated TLS versions or disabling certificate validation can expose your application to security vulnerabilities.","severity":"gotcha","affected_versions":">=8.0.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Verify the `bindDN` and `bindPassword` are correct for the LDAP server. For Active Directory, the `bindDN` is often the User Principal Name (UPN) or `sAMAccountName` in a specific format.","cause":"The Distinguished Name (DN) or password provided for the bind operation is incorrect.","error":"LDAP operation failed: LDAP_INVALID_CREDENTIALS"},{"fix":"Ensure the LDAP server is online and listening on the specified host and port. Check network connectivity between your application and the server, and verify any firewall rules.","cause":"The client failed to establish a TCP connection to the LDAP server, often because the server is not running, is unreachable, or the port is blocked by a firewall.","error":"LDAP operation failed: connect ECONNREFUSED"},{"fix":"Increase `connectTimeout` for connection issues or `timeout` for operation issues in the `Client` constructor options. Also, check network latency or server load.","cause":"Either the TCP connection attempt or an LDAP operation timed out before a response was received.","error":"LDAP operation failed: ETIMEDOUT"},{"fix":"This often points to an issue with the LDAP server itself returning non-standard or corrupt data. Review the LDAP server logs for errors related to the request. Ensure `ldapts` is up to date, as parsing bugs are sometimes fixed in new versions.","cause":"The LDAP server responded with malformed BER-encoded data, indicating an issue with the server's response or a parsing error in the client.","error":"LDAP operation failed: InvalidAsn1Error: invalid BER: expected BER length to be less than or equal to the amount of data in the buffer."}],"ecosystem":"npm"}