Systems · Concept · 13 min read

LDAP Explained: The Protocol Almost Every Login Still Goes Through

Two operations, a tree of names read backwards, and a default port that puts passwords on the wire in the clear. Here is what a bind actually does, why a filter looks like that, and what happens to all of it when the directory moves to the cloud.

Written by Marko Ristic, Editor Updated Sep 17, 2026
389The plaintext port a password should never cross
636LDAPS, encrypted from the first byte
1,000Entries an AD server returns before paging is required
2Operations in the whole protocol: bind and search
Short answer

LDAP is how an application asks a directory server who a user is and whether their password is correct. It is a protocol, not a product: Active Directory speaks it, OpenLDAP speaks it, and so does nearly every appliance with a box labeled "connect to your directory". The two operations are bind, which authenticates, and search, which reads.

  • LDAP is a protocol. Active Directory is a directory that speaks it
  • A simple bind on port 389 sends the password in the clear
  • A distinguished name is a path, so it changes when an object moves
  • Attribute names differ between products, which breaks copied configs
  • Cloud directories mostly do not speak LDAP at all
On this page

The treeThe LDAP tree, and how names are built

LDAP directory data is a tree, and every entry in it has a name built from its position, which is the part that trips people up first.

An entry's distinguished name, its DN, is the full path from that entry up to the root of the directory, written from the specific to the general. It looks like this.

CN=Ana Novak,OU=Finance,OU=Staff,DC=company,DC=local

Read it right to left. DC=company,DC=local is the root of the LDAP tree, derived from the domain name company.local. OU=Staff and OU=Finance are organizational units, containers within it. CN=Ana Novak is the user entry itself.

Three parts of that are worth knowing.

The DN is a path, not an identifier. Move the user account to a different organizational unit and the DN changes. Any application storing a DN as a permanent reference breaks the day somebody reorganizes the directory, which is why it should store a stable attribute instead.

The relative distinguished name is the leftmost part alone, CN=Ana Novak, which has to be unique within its container in the directory and not anywhere else.

Common LDAP attributes are worth memorizing because every configuration screen uses them: CN is common name, OU is organizational unit, DC is domain component, UID is user id, SN is surname, O is organization.

Every LDAP session is a sequence of these two operations, and understanding them is understanding the protocol.

An LDAP bind authenticates a user. The client sends a DN and a password, and the directory server says yes or no. There are three kinds of bind and the difference matters for security.

An anonymous bind sends no credentials at all. Many directory servers allow it for reading public information and many others refuse it outright, which is a common cause of an integration that works in one environment and not another.

A simple bind sends the user DN and the password in the request. Over port 389 with no encryption, that password crosses the network in the clear. This is the single most important security fact on this page.

A SASL bind uses a real authentication mechanism, usually Kerberos in a Windows environment, and never sends the user password over the wire at all.

An LDAP search reads directory information. The request carries a base DN saying where in the tree to start, a scope saying how deep to go, and a filter saying what to match. The directory server returns the matching entries and the attributes requested.

That structure explains most integration failures. An LDAP search returning nothing usually has the wrong base, a scope of base where it needed subtree, or a filter testing the wrong attribute.

FiltersLDAP filters, which look worse than they are

LDAP search filters use prefix notation and parentheses, and they read strangely until the pattern clicks: the operator goes first, then its arguments.

(uid=anovak)                       one attribute equals a value
(objectClass=person)               every entry of a type
(&(objectClass=user)(mail=*))      AND: users that have an email address
(|(department=Sales)(department=Marketing))    OR: either department
(!(userAccountControl=514))        NOT: excludes disabled accounts in AD
(&(objectClass=user)(memberOf=CN=VPN Users,OU=Groups,DC=company,DC=local))

The last one is the filter most people actually need, and it is the one every VPN appliance and web application asks for: only users in a particular group may sign in. The group is named by its full DN, so moving it in the directory breaks the filter.

The attribute names, which is where a configuration copied between two directory products quietly stops working.

What you meanActive DirectoryOpenLDAP
The login namesAMAccountNameuid
The full login, with domainuserPrincipalNameNot standard
Display namedisplayNamecn
Surnamesnsn
Email addressmailmail
Group membershipmemberOfmemberOf, if the overlay is on
The permanent identifierobjectGUIDentryUUID
Account is disabledA bit in userAccountControlpwdAccountLockedTime

The last row is the one that catches people. Active Directory has no simple disabled attribute: the state lives in a bit field, which is why the filter for enabled accounts looks like an incantation rather than a comparison.

Two practical points. Filters are evaluated on the directory server, so a broad filter across a large directory is slow, and narrowing the base DN helps more than tightening the filter. And attribute names differ between directory services: Active Directory uses sAMAccountName where OpenLDAP on Linux uses uid, which is why a configuration copied between the two rarely works unchanged.

SecurityThe LDAP security problem, and how it was fixed

Plain LDAP on port 389 has no encryption. A simple bind over it puts a user name and a password on the wire in a form anyone on the path can read. That is not a subtle security weakness, and it is still how a surprising number of printers, scanners and older appliances access the directory.

Two LDAP mechanisms fix it, and they are often confused.

LDAPS, on port 636, wraps the whole LDAP session in TLS from the first byte, the same way HTTPS does. It is straightforward, it is what most appliances support, and it needs a certificate the client trusts.

StartTLS, on port 389, opens a plain LDAP connection and upgrades it to TLS before any credentials are sent. It is the modern preference in the standards and it has one weakness: a client that fails to request the upgrade, or fails to check that it succeeded, carries on sending data in plaintext with no error.

Microsoft has been pushing this for years, and current Active Directory servers increasingly require signing and channel binding, which means a plain simple bind on 389 is rejected outright. That change breaks exactly the old devices described above, and finding them before it lands is the work.

The practical instruction: use 636 or StartTLS everywhere, and audit for anything still binding in plaintext. Directory servers log the source of unsigned binds, and that log is the list of devices to fix.

Against ADLDAP and Active Directory

LDAP and Active Directory get used interchangeably and they are not the same kind of thing.

LDAP is a protocol. A specification for accessing a directory, defined by the IETF and implemented by many directory services.

Active Directory is a directory service that speaks LDAP among several other protocols. It also uses Kerberos for authentication, DNS for locating services, and Group Policy for configuration management, none of which is LDAP.

So an application configured to authenticate users against Active Directory over LDAP is using one protocol out of the several the directory offers, and usually the least preferred one. Where the application supports Kerberos or a modern federation protocol instead, that is nearly always the better choice: no user password crosses the wire, and single sign on works.

The other common comparison is with SAML and OIDC. Those are web federation protocols based on redirecting a browser to an identity provider, and they are what a modern web application should use for authentication. LDAP is for applications and appliances that predate them or run outside a browser, and there are a great many of those.

The cloudWhat happens when the directory moves to the cloud

This is the question that arrives in every modernization project, and the answer surprises people: cloud directory services generally do not speak LDAP at all.

Microsoft Entra ID, formerly Azure AD, is an identity and access management service rather than an LDAP directory server. It handles authentication over OAuth, OIDC and SAML, which are the right protocols for web applications and useless to a printer. There is no LDAP endpoint to point a scanner at, and no port 389 anywhere.

Three paths exist, and choosing between them is the actual decision.

Keep a domain controller. The simplest answer for a building full of appliances. Cloud authentication for the web applications, on premises Active Directory for everything that only speaks LDAP, with the two synchronized. Most organizations are here and will be for years.

Run a managed directory service in the cloud. Entra Domain Services provides an LDAP and Kerberos endpoint backed by the cloud directory, so appliances have a server to bind to without one to patch. It costs real money per month and it is the answer when the only reason a domain controller still exists is LDAP access.

Replace the appliances. Slower, more expensive, and the only path that actually removes the dependency. Worth doing at the natural refresh point rather than as a project of its own.

The trap to avoid is discovering the dependency late. Before any plan to retire the last domain controller, search the server logs for every device still binding over LDAP. The list is always longer than the inventory, and it always contains at least one thing nobody remembers putting on the network.

PitfallsWhere people go wrong

Binding as a domain administrator. An application only needs read access to the directory information, and it is frequently given an account that could rewrite all of it. That password sits in the application configuration file, often in plaintext. Create a dedicated read only service account with no privileges beyond the LDAP search it performs.

Using port 389 with a simple bind. The user password is readable by anyone on the path. This is the security finding that appears in every audit, usually on a multifunction printer.

Storing a DN as a stable reference. It changes when the object moves in the directory. Store the objectGUID attribute in Active Directory, or entryUUID in OpenLDAP on Linux, both of which are permanent.

Setting the LDAP search base too high. Basing a search at the root of a large directory and relying on the filter makes every query expensive for the server. Base it on the organizational unit that actually contains the user accounts.

Copying a configuration between directory services. The attribute names differ. sAMAccountName, uid and userPrincipalName are three different things, and a configuration that assumes the wrong one returns no information and no useful error.

Pointing at one directory server by name. It reboots on patch night and the integration fails. Point at the domain name so the client can use any server, or configure two.

Forgetting the paged results limit. Active Directory returns 1,000 entries by default, and a client that does not implement paging silently receives truncated information. Every subtle "some users cannot log in" problem in a large directory is worth checking against this.

ONE DISTINGUISHED NAME, READ RIGHT TO LEFTCN=Ana Novakthe entryOU=Financea containerOU=Staffits parentDC=company,DC=localthe root of the treeread this wayMove the account to another organizational unit and the whole name changes, which is whyan application should store objectGUID rather than the DN as its permanent reference.THE THREE WAYS TO CONNECTPORT 389plaintext, simple bindthe password is readablePORT 389 + StartTLSupgrades to TLSfails open if uncheckedPORT 636, LDAPSTLS from the first bytethe safe defaultEvery audit finds a printer on the left hand box. Directory server logs name them.
A distinguished name taken apart, and the three ways to connect, one of which puts the password on the wire.

ComparisonLDAP, Kerberos and web federation, on what each one is actually for

CriterionLDAPKerberosSAML or OIDC
Sends a user password over the wireYes, on a simple bindNoNo
Works for a web applicationWorkableAwkwardNative
Works for an appliance or a printerYesRarelyNo
Single sign onNoYesYes
Reads directory data directlyYesNoThrough claims
Works outside the networkOnly over a VPNOnly insideYes, cloud native
Needs a service account on the serverYesNoNo
Effort to integrateLowMediumMedium

The first row is the security argument. LDAP survives because the bottom row is true and because appliances support no other authentication, not because it is the better protocol.

FAQFrequently asked questions

What is LDAP in simple terms?

The protocol an application uses to look up users and groups in a directory server, and to check whether a password is correct.

Is LDAP the same as Active Directory?

No. LDAP is a protocol for directory access. Active Directory is a directory service that speaks LDAP along with Kerberos, DNS and other protocols.

What is an LDAP bind?

The authentication step. The client sends a distinguished name and a password, and the directory server accepts or rejects it. Anonymous, simple and SASL are the three kinds.

What is a distinguished name?

The full path to an entry in the directory tree, written from the specific to the general, such as CN=Ana Novak,OU=Finance,DC=company,DC=local.

What port does LDAP use?

TCP 389 for plaintext and StartTLS, TCP 636 for LDAPS. Active Directory servers also use 3268 and 3269 for global catalog queries across a forest.

Is LDAP secure?

Only when encrypted. A simple bind on port 389 sends the user password in the clear. Use LDAPS on 636 or StartTLS on 389, and audit the network for anything still binding in plaintext.

What is the difference between LDAPS and StartTLS?

LDAPS wraps the whole connection in TLS from the start on its own port. StartTLS begins in plaintext on 389 and upgrades. Both are secure when implemented correctly, and StartTLS fails open if the client does not check.

How do I restrict access to one group?

With an LDAP filter on memberOf naming the group's full distinguished name. That is the setting almost every appliance calls a group filter.

Why does my LDAP search return no information?

Usually the search base is wrong, the scope is set to base rather than subtree, or the filter names an attribute this directory service does not use.

What account should an application bind as?

A dedicated service account with read only access to the part of the tree it needs. Never a domain administrator, because that password lives in a configuration file.

What is the 1,000 result limit?

An Active Directory server returns a maximum of 1,000 entries per LDAP request unless the client implements paged results. A client that does not receives silently truncated data.

Should new applications still use LDAP?

For a web application, no. Use a token based protocol such as SAML or OIDC. For an appliance, a printer or software that predates them, LDAP over TLS remains the correct answer.

Read next · Identity and access What Is MFA? A bind checks one password. Everything that makes that password sufficient sits above it. Open this next16 min
Also worth reading
One packet a weekA short, illustrated explainer every Tuesday. No vendor pitches, unsubscribe in one click.