How LDAP works
Suppose you're building a company directory. Every employee has a name, an email address, a phone number, a department, a job title. You add people when they join and remove them when they leave. Everyone needs to look each other up constantly: find Alice's email, list everyone in Engineering, check who has VPN access.
You could store all of this in a database, but look at the access pattern. You're doing far more reads than writes. People rarely change departments, but they look each other up hundreds of times a day. You want something optimized for fast lookups, not complex transactions. You want a directory.
A directory is a specialized data store designed for exactly this: storing information about people and things in an organization, and looking it up quickly. LDAP (Lightweight Directory Access Protocol) is the standard protocol for talking to these directories. It was designed in the early 1990s as a simpler alternative to the X.500 Directory Access Protocol, which required the full OSI networking stack. LDAP runs over TCP and strips the protocol down to the essentials, which is where "Lightweight" comes from. Almost every large organization uses it, usually without anyone noticing.
A list of people
The simplest directory is a flat list, where each entry has a name and some associated data. When someone asks "where's Diana?", you start at the top and scan down until you find her.
Try searching the list below, then try adding a duplicate name:
You run into two problems right away. Searching is slow: you scan every entry until you find a match, which is fine for six people but painful for sixty thousand. Uniqueness also breaks: add a second Bob Smith (different department, different email) and you can't tell them apart by name alone.
A flat list has no concept of structure. Departments, teams, and locations exist only as text fields on each person, not as organizational containers. You can't ask "show me everyone in Engineering" without scanning every single entry.
So you need structure, a way to organize entries into groups, with groups inside groups.
Toggle between the flat list and a tree view of the same data to see the difference:
In the tree view, the structure is explicit. People live under People and groups live under Groups, so if you want everyone in Engineering, you walk directly to the Engineering branch instead of scanning the whole list. The tree also solves the duplicate name problem, because two people named Bob Smith can exist in different branches and their positions in the tree make them unambiguous.
Organizing into a tree
LDAP directories store data in a tree called the Directory Information Tree, or DIT. The root of the tree represents the organization. Below it, organizational units (OUs) act as containers, and below those, individual entries represent people, groups, services, or anything else the organization needs to track.
Step through the construction of a directory tree below:
The root entry uses domain components (dc), so dc=example,dc=com mirrors the organization's DNS domain name split into parts. Below that, organizational units (ou) group entries by purpose: ou=People for employees, ou=Groups for teams, ou=Services for infrastructure. Individual entries then use common names (cn) like cn=Alice Johnson or cn=Engineering.
These prefixes (dc, ou, cn) are called attribute types. Each node in the tree has a Relative Distinguished Name (RDN), one or more type=value pairs that identify it among its siblings. Most RDNs are single-valued in practice, but multi-valued RDNs are allowed (e.g., cn=Kurt+l=Redwood Shores). cn=Alice Johnson is Alice's RDN within the ou=People container.
But an RDN only identifies a node relative to its parent. If there's a cn=Alice Johnson under ou=People and another under ou=Contractors, the RDN alone isn't enough.
Try finding Alice by her RDN alone:
To resolve this, we need a full address.
Naming things in trees
Click any node in the tree below to see the full path from that node back to the root:
The full path from a node to the root, written as a comma-separated list of RDNs, is called the Distinguished Name (DN). Alice's DN is cn=Alice Johnson,ou=People,dc=example,dc=com, which reads left to right from the specific entry (the leaf) to the general (the root), like a file path written backwards.
Every entry in the directory has a unique DN, because no two siblings can share the same RDN. This gives you a global addressing scheme: given a DN, you can navigate from the root, following each component, straight to the entry.
You use the DN to refer to entries in LDAP operations. When you want to read Alice's record, you ask for cn=Alice Johnson,ou=People,dc=example,dc=com. When you want to authenticate as Alice, you bind with her DN.
What's inside an entry
A DN tells you where an entry lives in the tree. But what does the entry actually contain?
Click different nodes below to explore their attributes:
Every entry is a collection of attributes, which are named values. An attribute has a type (like mail or telephoneNumber) and one or more values. Alice has one email address, but a group entry has multiple member values, one per member.
Notice how different types of entries have different attributes. A person entry has mail, telephoneNumber, and title, while an organizational unit entry has just ou and description, and a group entry has member with multiple DNs. What determines which attributes an entry is allowed to have is its object class.
What an entry is allowed to hold
An object class defines what attributes an entry can (or must) have. Object classes form an inheritance chain, where each class extends the one above it and adds more attributes.
Step through the object class chain below:
The base class top requires only objectClass itself. The person class adds cn (common name) and sn (surname) as required attributes, plus optional ones like telephoneNumber. The organizationalPerson class extends that with title and ou, and finally inetOrgPerson (the most commonly used class for people) permits internet-era attributes like mail and uid. These attribute types are defined in other schema RFCs; inetOrgPerson doesn't invent them, it just says that entries of this class are allowed to use them.
An entry can have multiple object classes. A typical person entry lists objectClass: top, person, organizationalPerson, inetOrgPerson and inherits all attributes from the entire chain. The schema is enforced by the server, so if you try to add a mail attribute to an entry that only has the person object class (without inetOrgPerson), the server rejects the operation.
Because of this schema system, the directory is self-describing. A client can query the schema to discover what attributes exist, what object classes are available, and what the rules are.
Finding things
Looking up entries by DN requires knowing the exact address. In practice, the most common operation is search: "find all engineers," "find everyone whose email contains @example.com," or "find the group called Engineering."
Every LDAP search has three parameters: where to start (the base DN), how far to look (the scope), and what to match (the filter).
Click a node to set the base, then toggle between scopes to see how each one works:
Base scope returns only the entry at the base DN itself. One level returns only the direct children of the base entry, without including the base entry itself. Subtree returns the base entry and all of its descendants recursively, which is the scope most real searches use, typically with the root as the base to search the entire directory.
The scope determines which entries are candidates, and the filter narrows them down. Try the preset filters below:
Filters use a prefix notation with parentheses. The simplest filter is an equality check: (cn=Alice Johnson) matches entries where the cn attribute equals "Alice Johnson." The presence filter (mail=*) matches any entry that has a mail attribute at all, and substring filters like (title=*Engineer*) match any entry whose title contains "Engineer." You can also combine filters with & (AND) and | (OR), so (&(objectClass=inetOrgPerson)(title=*Engineer*)) finds all people whose title contains "Engineer."
Here's a complete search operation. It uses subtree scope from the root with the filter (objectClass=inetOrgPerson), which matches all person entries:
The server walks the tree in order, checking each entry against the filter. Entries that match get added to the result set and entries that don't are skipped, so the final result is the set of all entries in scope that satisfy the filter.
Who gets to see what
An open directory where anyone can read everything isn't practical. Salary data, private phone numbers, and group memberships all might need to be restricted. LDAP controls access through binding, which is the process of authenticating to the server.
Step through a bind operation below:
Before binding, a connection is anonymous. The client sees only what the server's access control rules allow for anonymous users, which is often limited to basic attributes like names and email addresses. To see more, the client sends a bind request containing a DN (identifying who they claim to be) and a password.
The server looks up the entry at that DN, checks the password against the stored hash, and responds with success or failure. After a successful bind, the connection carries that identity, and what you can read, modify, or delete from that point on depends on the server's access control rules. These rules are vendor-specific; LDAP itself doesn't standardize an ACL mechanism.
A simple bind sends the password in the clear, so in production you always wrap the connection in TLS. You can do this with LDAPS (on port 636) or the StartTLS extended operation, which upgrades a plain connection to TLS in-place on the standard port 389.
Try toggling between a correct and incorrect password in the demo above and notice how a failed bind leaves the connection anonymous.
Where LDAP lives today
LDAP is invisible infrastructure. It underpins directory lookups and authentication flows across corporate networks, often without anyone realizing it's there.
When you type your username and password at a company login screen, the application often searches the LDAP directory for your username, gets back your DN, then attempts a bind with your DN and password. If the bind succeeds, you're in. OS-level domain logon usually uses Kerberos or NTLM instead of a simple LDAP bind, but the directory behind those protocols is the same. That's why changing your password in one place (the directory) changes it everywhere: every application authenticates against the same directory.
Active Directory, Microsoft's directory service, is the most widely deployed LDAP server. It powers authentication and authorization for most corporate Windows environments. OpenLDAP is the most common open-source implementation, used in Linux environments and cloud infrastructure. Cloud providers offer managed LDAP services: AWS Managed Microsoft AD, Microsoft Entra Domain Services, and Google's Cloud Identity Secure LDAP (for connecting apps) or Managed Service for Microsoft Active Directory (for managed AD with LDAP/LDAPS).
Beyond authentication, directories are the source of truth for organizational data. Email clients query LDAP for address books, VPN servers check group membership to decide who gets access, and HR systems sync employee records to the directory. Single sign-on systems use it as the identity backend.
The protocol itself is simple: connect, bind, search, compare, add, modify, delete, unbind. What makes it useful is the data model, with its tree structure, schema enforcement, and DN addressing, combined with the fact that everyone agrees to use the same one.