LDAP Survival Guide

Last modified 02 Mar 2022 10:54 +01:00

Lightweight Directory Access Protocol (LDAP) is a directory protocol that originated in 1990s. It is based on older X.500 work that goes back even further, into the 1980s. Nowadays, LDAP is usually used to maintain user accounts in a central directory server.

LDAP is a widely used protocol. Some (usually older) engineers like LDAP. And there is a lot to like about it. It is elegant in its simplicity, it is very efficient, it has pretty much everything that we valued in 1990s. However, many engineers (usually younger) fear and hate LDAP. And there is a lot to dislike about LDAP. Mostly its inability to correct its mistakes and adapt to a changed world.

This document is a description of common LDAP problems, and the ways how to work around them. If you are doing something simple with LDAP, such as doing simple bind and search, you will not need this guide at all. However, if you are going to deal with LDAP groups, paged searches, synchronization, or if you use LDAP for identity management, you will probably find this guide useful. There are many conventions, pitfalls, unwritten rules and undocumented practices in the LDAP world. This document tries to help you navigate these treacherous waters.

This guide is written by an engineer that deals with LDAP since late 1990s. If you are an old LDAP engineer, you will quite certainly do not like my point of view. I’m not trying to change your opinion. That is not the purpose of this guide. What I’m trying to do is to give tips on how to survive in the LDAP labyrinth. This document is meant to help pragmatic engineers that need to get things done.


The most common use of LDAP is to enable password-based authentication for applications. The applications use bind LDAP operation to authenticate to the directory server. If that operation is successful, the application assumes that the password was correct. There is a wrong way how to implement this authentication (using dn pattern) and a less wrong way how to do it (search then bind). However, there is no correct way, as LDAP was never designed to be an authentication server. Yet, this remains the most widespread use of LDAP protocol by far.

Of course, this is causing a lot of problems. This is practically limited to password authentication. Even though there is SASL layer that can support other authentication mechanisms, servers are not equipped to be authentication servers in the first place. LDAP has no concept of a session, therefore the directory server cannot be used for session management and auditing. It was never meant to be used in this way. But it is.

While this is not a problem of LDAP protocol per se, it tells a lot about the LDAP world. LDAP is used in a way that was not intended and that the original designers never anticipated. A protocol created in 1990s, with roots in telecommunication world of 1980s, is used to handle 21st century use cases. It is no wonder it is not very well-equipped for that.

What To Do About It?

Nothing. That is the way it is. LDAP was not designed to be an authentication protocol. Yet, it is used for authentication most of the time. LDAP password authentication (LDAP bind) is the simplest way how to centralize password authentication for simple and legacy applications.

However, if your application is any good, it will probably include support for real authentication or access management protocols such as OpenID Connect (OIDC) or SAML. Use these methods instead of LDAP if you can. They can provide much more than a simple password authentication. They are the way to the future.

Account Management

Certainly, LDAP was never designed to be an authentication protocol. However, LDAP was designed to be a directory access protocol. Most LDAP servers are in fact directory servers. A prominent life form in the directory universe is a user account. It would be fair to expect that LDAP is an excellent tool for account management. Sadly, it is not.

Multiplicity Of Names

LDAP schema was inspired by older X.500 data models. That is perhaps the origin of chronic "multiplicity" of LDAP data structures. Name of the user is supposed to be stored in cn attribute. The cn, as well as sn, givenName, uid and most other LDAP attributes are multi-valued. This makes some sense for uid, which usually stores user’s login name. This could be used to support username aliases. However, even that is far from being perfect. Yet, this multiplicity makes very little sense for cn, sn and givenName. Overwhelming majority of deployments are using these in a single-valued form. I would bet my lunch that most applications are going to throw ugly errors if they ever encounter more than one value in these attributes. Why LDAP mandates that these values must be multi-valued? Strictly speaking, standard-compliant LDAP clients MUST be able to handle multi-valued names. But is the client supposed to handle it? LDAP does not guarantee ordering, therefore taking the first value makes no sense.

What To Do About It?

This one is simple. Never ever use cn, sn, givenName and similar attributes as multi-valued attributes. Always use them as single-valued attributes.

There are some cases when multi-valued nature of uid makes sense. However, it is better to avoid that as well, unless you really know what you are doing, and you are fully aware of all the consequences.

This is exactly what almost all the LDAP clients do. Therefore vast majority of LDAP clients are not perfectly LDAP-compliant. Yet, this non-compliance does not make any significant problems in the real world. This is LDAP world, you just have to follow unwritten LDAP conventions in addition to LDAP standards and you are fine.

Blast from the past
There are other places of the schema where you can feel the 1980s. Obviously, there is facsimileTelephoneNumber and telexNumber, which are a reason for a nostalgic smile. This may be funny, but it is not a real problem. The problem is that the schema is not prepared for future development in communication. There is no concept of contact channels. There is even no concept of "work phone number". Not to mention chat applications and social networks. The schema is frozen in 1990s.

Account Activation

Perhaps the most painful problem is that there is no account disable mechanism. Yes, that is how it is. There is no standard way how to disable an account in LDAP directory. Most engineers would consider control over account activation to be one of the very basic account management functionalities. It is certainly much more important than telexNumber. Yet, LDAP does not have it. This is somehow understandable. The telecommunication world of 1980s was very different when compared to the world today. Telex number was much more important than account disable back then. The problem is, that this was not corrected in 1990s when X.500 was transposed to LDAP. And it was not fixed up until this day.

I can understand and even tolerate lot of LDAP issues. But I cannot understand this one.

What To Do About It?

Mechanism to disable an account is almost always needed in practice. Therefore most LDAP servers have a proprietary mechanism to do that. LDAP clients must use non-standard ways to implement functionality that is needed by almost every deployment.

This is what individual LDAP servers do:

iPlanet family: (RedHat/Fedora) 389 Directory Server, Sun/Oracle DSEE

Use nsAccountLock operational attribute.

OpenDS family: OpenDS, OpenDJ, wren:DS, UnboundId

Use ds-pwp-account-disabled operational attribute.


Bad luck. You cannot do it. You can use password policies to disable password authentication. This may work for simple cases, but it will not disable all account functionality. E.g. alternative authentication mechanisms (such as UNIX ssh keys) will still work. You can create a custom attribute for this, but then you need to modify all your applications to support it. There are tricks how to disable bind and hide disabled accounts using ACLs. But that is also problematic. In fact, there is no good way how to do account disable in OpenLDAP.

Active Directory

Use userAccountControl attribute. This is a very ugly attribute, it is difficult to work with. But it works, in a way.


LDAP Groups are one of things that are unbelievably wrong. There is no nice way how to put it. Almost everything that could go wrong went wrong when LDAP grouping mechanism was designed.

Group Has Members

Typical LDAP group contains a list of member accounts (or other groups). This may be an obvious way to design a group schema. It has some advantages, most notably in simplified access control. But it is a nightmare from operational perspective.

Common LDAP server has a couple of big groups, groups that almost every account is a member of. This means that there is an LDAP object that has huge number of values in one attribute. Adding a member to such a group is very painful. The operation is often very slow. Yet, this is an operation that happens almost every time an account is added or removed. You have to suffer the slow down for every group involved, as there is no way how to update membership in several groups in one operation. LDAP servers pride themselves to be lightning-fast. But does it matter that you can create an account under 1 millisecond, when full provisioning of that account also means assigning it to groups, which literally takes several seconds to complete?

What To Do About It?

There is not much you can do about this. Older LDAP servers (notably the iPlanet family) are very problematic with big groups. Some LDAP servers (notably OpenLDAP) can make fast updates even for big groups. You can replace your LDAP server with a faster one. However, due to subtle incompatibilities between servers, replacement of a LDAP server is a slow and risky process.

However, even if your server can handle big groups, you still have to be careful in your application when working with them. Frequently reading group entry with a huge amount of members is very likely to ruin your performance. Make sure you are explicitly requesting only the attributes you need when reading the group. I.e. avoid reading the member attribute. The best approach is not to read the group entry at all. Use the non-standard member of mechanism to determine group membership. Use non-standard permissive modify when modifying the group. These two are the basic survival tools when dealing with groups.

As you will see later, working with LDAP groups is like trying to cross a minefield. Prepare for many trials and errors. You will encounter some of the problems only when you are in full production environment. However, with a bit of luck, you can have a working solution at the end.

Member Of

The fact that a group has a list of members makes it a bit difficult to determine group membership for a user. In standard LDAP, the client has to search all groups, looking for a particular member DN. LDAP deployments often rely on groups for authorization purposes. Which means that the client has to make one additional request every time to determine group membership. Given the presence of big groups, this request may not be entirely fast.

This problem was, of course, recognized in the past. Therefore almost every LDAP server has a "member of" mechanism that reflects group membership on user entry in a form of virtual attributes. However, this mechanism is not standardized. The virtual attribute is memberOf in one server, isMemberOf in another. This is yet another non-standard mechanism that is crucial for almost all LDAP clients.

What To Do About It?

Always use the member of mechanism when it is available. It is basic survival tool when working with groups. Almost all server have such mechanism, many servers have it enabled by default. OpenLDAP is one popular server that does not have it enabled by default, however there is a special memberOf overlay that provides this functionality.

No Empty Groups

To make the situation entirely bizarre, LDAP standard specifies that group member is a mandatory attribute. Yes, every group in standard-compliant LDAP server must have at least one member. The official reason for this decision is to avoid empty groups. This is a noble goal. The trouble is that it makes no sense whatsoever.

This means that groups cannot be pre-provisioned. This means that if the last member of the group is removed, the group has to be removed as well. This means that if a group is temporarily empty, it has to be deleted and re-created. Re-created group will have a new entryUUID, therefore it will be considered to be a new object by smart LDAP clients. This is going to make a big mess for any synchronization mechanism. As empty groups cannot legally exist in standard LDAP server, information about empty groups has to be maintained in some external database. Worst of all, this means that empty groups are invisible to system administrators. All in all, this is not going to work in practice.

Most LDAP deployments work around this in one way or another to make it suitable for real-world deployments. The deployments that insist on full LDAP compliance usually add fake member to each group. That works, although your security officer is not going to be entirely happy about it. The quasi-strict way how to work around it would be to add the fake member to empty groups only. Unfortunately, that will not actually work either. In that case, every operation that adds a new member must also remove the fake member. However, due to another LDAP peculiarity (see "permissive modify" below), the server MUST fail such operation if the fake member is not there. Therefore the client must first check whether the fake member is a member of the group. However, that check is not reliable, as standard LDAP does not have consistency guarantees to support this case. The fake member might have been removed in the time before the check and the modify, therefore the modify operation can still fail. It is even worse if we try to add fake member to an empty group, however I would like to leave that particular algorithm to the reader to figure out. All in all, this is how LDAP standard makes a simple thing unbelievably complex.

What To Do About It?

In fact, the only reasonable way is to blatantly violate LDAP standard and make the member attribute optional. That is what many LDAP servers do, anyway:

iPlanet family: (RedHat/Fedora) 389 Directory Server, Sun/Oracle DSEE

You are fine. The vendor has already violated LDAP specifications for you.

OpenDS family: OpenDS, OpenDJ, wren:DS, UnboundId

You are fine. The vendor has already violated LDAP specifications for you.


Locate server schema. You are looking for cn={0}core.ldif file. Change the entries for groupOfNames and groupOfUniqueNames, moving the member attribute from MUST to MAY.

Active Directory

You are fine, in a typical Microsoft way. Active Directory is not using LDAP grouping mechanisms.

This is a shameless violation of LDAP specifications, which quite explicitly prohibit such changes in standard schemas. Yet, it is the only sensible thing to do. You do not need to feel bad about it. It is not your fault. Most LDAP servers, Active Directory, eDirectory and similar LDAP-like servers, pretty much everybody has some ready-made solution for this problem. Perhaps the only popular LDAP server that still adheres to this insane part of LDAP specifications is OpenLDAP.

If you really have to strictly follow LDAP specifications there are some alternatives. Unfortunately, they are all very painful.

  • You can add dummy account to every group. Then they group will always have at least one member. If you do not enforce referential integrity, then it may be just a DN of non-existent entry. Just make sure such entry cannot be created by mistake. Then you are relatively safe. If case of referential integrity, you will probably need real account. Good luck negotiating that with your security officer and auditors.

  • You can dynamically add/remove dummy account when the group is empty. Theoretically. However, the algorithm is insane, and it is unreliable. Additionally, it has almost the same disadvantage as having the dummy entry in the group all the time. Do not do this, for the sake of your mental health.

  • You may try to delete empty groups. However, the algorithm is not trivial and this has a lot of disadvantages. Even worse, system administrators will hate you. Support engineers will hate you. Compliance people will hate you. Try to be a nice person and do not do this.

  • You can forget about groupOfNames and groupOfUniqueNames and use your own grouping mechanism. Create your own myCustomGroup object class and make the member optional. This is the right solution, at least in theory. However, you should better be prepared for huge pile of unexpected problems along the way. Your LDAP server will not know anything about myCustomGroup, therefore you will not be able to use it in ACLs and similar mechanisms. Your applications will not know the group either. Some applications are configurable, and you can make it work. However, too many applications still stubbornly expect groupOfNames or groupOfUniqueNames. These groups are LDAP standard after all, are they not? There are many problems if you choose this route. Do not do this unless you are really desperate.

See? The best place is to fix the problem is at its origin. Therefore go ahead, violate LDAP specification and never talk about it again.

Groups, Groups and Groups

Now, the LDAP group saga still does not end here. LDAP has two object classes for groups. They are pretty much the same, except that they are different. There is groupOfNames and groupOfUniqueNames. The former has member attribute, the later has uniqueMember attribute. That is the only important thing that makes any difference in practical deployments. There is also a subtle difference in syntax of the member attributes, but that difference is negligible for pretty much every single LDAP deployment.

Some LDAP servers prefer groupOfNames, other prefer groupOfUniqueNames. Some applications are hardwired for groupOfNames, others required groupOfUniqueNames which means that they will not interoperate. Most applications just resigned to standards and made this configurable. And then there are other grouping mechanisms, such as posixGroup. Even more grouping mechanisms was proposed or implemented in various LDAP servers in proprietary forms. LDAP grouping mechanisms would fill a mid-size ZOO and a large lunatic asylum.

What To Do About It?

There is no good solution here. Try to figure out whether your applications would like to have groupOfNames or groupOfUniqueNames. Luckily, many applications are configurable, but certainly not all of them. Also, look at your LDAP server. Some LDAP servers support just one of them in ACLs.

Overall, this is an acrobatic balancing act. In the worst case you will need both groupOfNames and groupOfUniqueNames and you will need to manage membership in both. This is also the case if you need posixGroup or any proprietary or custom grouping mechanism. Decent Identity Management (IDM) system is a must here.

Search, Paging and Sorting

LDAP is lightweight. In some aspects it is perhaps too lightweight. There is a very elegant and simple search operation, which is a universal tool for data retrieval. The client usually looks for one particular entry. LDAP is great for that. However, long search requests are a big problem. There is no good way for a client to retrieve a lot of entries. Why would a client need to retrieve a lot of entries? Maybe there is a synchronization or reconciliation process that need to make sure that the data are consistent. There may be an inspection process that checks for policy compliance. Or we may need to create a report of the data. Long search operations are needed more often than LDAP authors anticipated.

The simplest option for a long search operation is to use plain LDAP search operation. However, most directory server will refuse to do that, enforcing "size limit" on number of returned entries. Even if administrator disables the limit, there are still drawbacks. The entries are returned sequentially over a single TCP connection. If that connector is broken, the search needs to be re-started from the beginning.

Then there is "Simple paged results" (SPR) LDAP control (RFC2696). This control can be used to retrieve the results in several requests. This is a common method how to overcome server size limit. However, the entries are still delivered sequentially. With some luck, this could be used to resume a search if the connection is broken. Although the actual algorithm is not easy and it may not work for every server. However, this is still very simple paging, e.g. there is no way how to specify starting offset.

Alternative of SPR is Virtual List View (VLV). This is a non-standard, but very widely used LDAP control. It can be used to request particular "page" of the results. However, there are still many gray zones. It is not clear what is the impact on the server, as this needs Server Side Sorting (SSS, RFC2891) to work reliably. Therefore, the server usually needs to create temporary data structures that span several requests, and it is not clear how to do that efficiently. It is quite difficult to create LDAP client that gets the job done and it still nice to the server.

There are at least three approaches for long searches. SPR and VLV are often supported by servers, but each server has its own peculiarities. None of these approaches work universally for all the servers. Therefore it is quite hard to write an interoperable LDAP client. Which somehow diminishes the value of having a standard in the first place.

What To Do About It?

Fortunately, most servers support both SPR and VLV and the support is also enabled by default. Again, with a notable exception of OpenLDAP, where you need sssvlv overlay. However, that does not mean that all servers behave the same. There are subtle differences in server behavior, especially for VLV. For example, OpenLDAP needs to set a special prtotal limit even for VLV searches. Probably the only thing you can do is to experiment with your specific server and configuration.

Permissive Modify

LDAP makes updates unnecessarily difficult. LDAP standard mandates that server MUST fail if client tries to add a value that is already present or remove a value that is not present. This might have looked good on a drawing board, but it is a disaster in practice. As LDAP is built with weak consistency in mind, re-adding existing value or deleting already deleted value is a common occurrence. LDAP data are unordered by design, therefore there are no ordering issues that would prohibit a "permissive" modification. Yet, LDAP standard explicitly prohibits it. Which means that standard-compliant LDAP client MUST always check whether a value is present in the entry before modification. However, such check is not reliable anyway, as there is no guarantee that the entry was not modified between the check and the update. Therefore there is no good way how to do it. Even having a special error response that would reliably indicate the problem could make the problem less painful. But LDAP does not have it.

Similarly to other LDAP problems, this problem is know for a long time. There is a Permissive Modify control that changes server behavior. It is a part of basic survival kit for many LDAP client authors. Yes, you guessed it. This control is not standardized. Also, it is not supported by all LDAP servers. In particular, (Fedora/RedHat) 389 Directory Server does not support this control. Which makes it very painful to work with that server.

What To Do About It?

It depends on what LDAP server do you have:

(RedHat/Fedora) 389 Directory Server,

Bad luck. No support for permissive modify. I’m sorry, there is nothing we can do for you.

Sun/Oracle DSEE

Not sure. Do you know if permissive modify is supported here? Let me know.

OpenDS family: OpenDS, OpenDJ, wren:DS, UnboundId

You are fine. Permissive modify is supported.


Permissive modify is supported, but it is not advertised in root DSE. Therefore applications cannot discover it automatically. You have to explicitly force the applications to use it.

Active Directory

You are fine. Permissive modify is supported.

Distinguished Names

Distinguished name (DN) is primary object identifier in LDAP. The look like this:


Surely, they are not the prettiest or shortest kind of identifier out there. However, this is just a cosmetics compared to other problems.

Firstly, the identifier depends on a location of an object in a directory. Which means that the identifier is going to change when the object is moved.

Secondly, the identifier often contains name of the object, such as username or common name. Which means that the identifier is going to change when the object is renamed.

DN is the primary identifier in LDAP, which is required for almost all LDAP operations to work. And yet, it is not exactly stable. This means that many operational procedures of LDAP directories are designed to minimize moving and renaming of objects. Which is a serious limitations for LDAP directories.

Yet, this gets even worse. The real nightmare starts when DNs are compared. For example, are the following DNs all the same, or are they different?


By now you should not be surprised by the answer. The answer is "it depends", of course. To be exact, it depends on the schema. Whether specific value is compared in case-sensitive or case-ignore way depends on definition of the attribute type. If a specific attribute is defined as case-sensitive, that part of DN has to be compared in case-sensitive way. If an attribute is defined as case-ignore, then that specific part should be compared in case-insensitive way. Unless you have complete schema information, you cannot decide whether DNs are same or different. Isn’t that cute?

Luckily, most commonly-used LDAP attributes are defined as case-ignore strings. Therefore, many LDAP implementation (especially the clients) just assume that DNs are completely case-insensitive, and compare them in case-ignore way. Which is, strictly speaking, not correct. But it is the only practical way to keep your sanity. Trust me. I have spent several days on a futile attempt to implement correct comparison algorithm that would work with at least two common LDAP servers. Did not work. The algorithm is very fragile, even small deviations from standard schema could ruin it completely. It is not worth trying.

What To Do About It?

When you are doing anything serious with LDAP, do not rely on DNs. Use other identifiers, such as entryUUID or its proprietary equivalents (such as GUID in Active Directory). Oh yes, this is going to be painful, as now you need to translate your entryUUID to DN for a lot of LDAP operations. Welcome to the LDAP land.

However, many applications do rely on DNs. If you move or rename an object, such clients wil not be able to find it. Therefore, design your directory structure to avoid moving and renaming objects. Avoid hierarchy. Put all your users into a single OU. Do not user full names in DN. Avoid using any attribute that is likely to change.

As for the DN comparison, just cut your losses and use case-ignore comparison for all DNs. This is what many implementation are doing anyway, therefore it became a de facto standard. Which means that you should never use a case-sensitive attribute in your DNs. Your clients will treat that as case-ignore value anyway.


X.500 was built with a vision of a world-wide distributed phone book. Some design decisions of X.500 made sense in that environment. However, when X.500 was "lightweighted" to LDAP, it took several X.500 concepts that do not fit into LDAP that well. The concept of object identifier (OID) is one of them.

The original idea was to make OID globally-unique. Anybody can register its own OID subtree and create unique OIDs for object classes, attribute names, controls and other LDAP creatures. That would make perfect sense, only if LDAP clients would use 0.9.2342.19200300.100.1.1 instead of uid. Surprise, surprise, engineers tend to like uid a bit more than 0.9.2342.19200300.100.1.1. Therefore, the OIDs do not really work any more. They just make the entire LDAP world look quite scary, especially for younger engineers. In fact, many LDAP servers do not require numeric OIDs at all. Perhaps the only two things were OIDs are still used are LDAP controls and extensions.

What To Do About It?

Try to enjoy the geeky look of OIDs. When you talk about OIDs with your colleagues, you will gain an aura of an engineering wizard. You can pretty much ignore OIDs otherwise. Even if you are extending schema, many servers (e.g. iPlanet and OpenDS family) allow you to use plain stings instead of OIDs. It is OK to use this option.

Replication and Synchronization

Directory servers are built to be lightweight. The simplicity of LDAP data structures has its benefits. The servers can provide great performance with low resource consumption. However, the most important benefit comes from X.500 legacy. Directory servers are meant to be horizontally scalable, they should work as a distributed system.

As directory servers are in fact just databases, replication capabilities are absolutely crucial for horizontal scalability. In essence, LDAP has all the prerequisites to be a good foundation for a replicated database. There is no requirements for ACID properties, consistency guarantees are reasonably low, data models are simple. However, LDAP standards somehow fail to capitalize on that.

There are replication mechanisms, but almost all of them are proprietary. There is one "standard" replication protocol (RFC4533), but even that is designated as experimental and it is not widely adopted. Standardized replication would be an ideal method to implement synchronization mechanisms, e.g. to synchronize content of directory system with identity management systems. However, directory servers provide proprietary, and often inferior mechanisms for synchronization. This means that every integration of LDAP server synchronization mechanisms is an adventure.

What To Do About It?

For replication, please contact your vendor.

Forget about cross-vendor replication, that almost never works reliably. Some servers have it, e.g. OpenLDAP can replicate to AD. However, AD does not follow standard schema - and as we have seen, strictly following LDAP specifications does not really makes sense. Therefore it is almost certain that you will need to transform the data as they move between servers. Identity management (IDM) system can help you with that.

Which leads us to synchronization capabilities. These vary for each server:

iPlanet family: (RedHat/Fedora) 389 Directory Server, Sun/Oracle DSEE

There is "Retro changelog" capability, exposing changes in cn=changelog LDAP subtree. This mechanisms somehow works. However, server based on older code (such as 389 Directory Server) have inferior implementation of the changelog. Detecting deleted objects and renames is problematic.

OpenDS family: OpenDS, OpenDJ, wren:DS, UnboundId

These servers have "Retro changelog" capability as well. This version of the changelog works quite well.


There are several mechanism. There is syncrepl (RFC4533), which could theoretically be used for synchronization. However, for some reason, this mechanism is not popular and it is poorly supported by the clients. Then there is an access log mechanism. We do not have sufficient data about the reliability of this mechanism so far. (Do you have the data? Please contact us.)

Active Directory

This is Microsoft, of course there is a proprietary mechanism. Microsoft mechanism is called DirSync. It is a special LDAP control that is added to a regular search request. Quite surprisingly, this is a very simple and effective mechanism and it seems to work well.

There is always an option to use modifyTimestamp for synchronization. This is a simple and popular method. The only problem is that is does not really work. Firstly, it cannot detect deleted objects. Secondly, it is sensitive to good time synchronization (on millisecond granularity). Thirdly, some objects need to be processed twice to make it reliable. Overall, this is very bad and unreliable method. Use only in case when there is no other option available.


There are few more things:

  • Access control lists (ACLs) are used by almost all the servers to control access to entries and attributes. Yet, the syntax of the ACLs is not compatible.

  • Almost all the servers implement password authentication. Majority of LDAP requests for most servers will be bind requests that check the password. Yet, password policies and lockout mechanisms are different for all the servers.

Most importantly of all, most servers generally deviate from LDAP standards. For example, 389 Directory Server (and most of the iPlanet family members) allows attributes that contain hash (#) in attribute name. This makes data essentially unportable to other servers. It even prohibits standard-compliant LDAP clients to interoperate with 389 Directory Server. Active Directory takes even more liberties. For example, AD allows any attribute to be set on entries, even if the attribute is not allowed by the schema. This is nightmare for schema-aware LDAP clients. Every server has some issues with standard compliance. As far as I am aware, there is no LDAP server that is 100% standard-compliant. Which means that standard-compliant LDAP client is a completely useless piece of software.

What To Do About It?

You have to live with these. Every server has its own way. Every server has its own quirks and peculiarities. It is what it is. You need to learn them and work around them.


Do not rely on "LDAPv3 compliant" and other marketing declarations. As you have seen, LDAP compliance is not a sufficient condition for interoperability. In fact, strict LDAP compliance is often an obstacle.

Build your solution with the specific server (and version) that you have chosen. Test the solution with that server. Test the solution, even if it comes from a vendor and it has "LDAPv3 compliant" stamp. Test everything before making a commitment.

Creating LDAP client that is interoperable with several servers is a huge undertaking. I know, I have done it, in a form of midPoint LDAP Connector. It took man-months of intense work, years of time, it involved building of testing environment, many trials and errors. There were non-trivial fixes that we needed to make in Apache Directory API and Apache MINA. After all that work, the connector is still not 100% interoperable with all major LDAP servers. Even more work will be need in the future.


There you have it. You may try to create software that strictly adheres to LDAP standards. However, such software will be useless. It is important to know LDAP standards. But it is even more important to know when to deviate from the standards. You have to deviate from the standards to survive.

I do not blame the authors of LDAP protocol. In fact, I have a great respect for them. They have done their best, back in 1990s. The fact is that it is not 1990s any longer. LDAP standards need maintenance. The standards need major revision and improvements. That did not happen. There were some minor updates, some proposals. No systemic review.

I was discussing these issues with various members of LDAP community during the years. Unfortunately, there seems to be almost no interest in the community to fix the problems. I have made my last attempt several years ago. All my efforts were useless. Therefore I have decided to stop trying to fix the unfixable. We have to live with what we have.

LDAP is a legacy technology now. It has all the characteristics of a legacy technology: it is flawed, it cannot be fixed, and you need unwritten arcane knowledge to work with it. Therefore we have to deal with LDAP accordingly to its status.

My recommendation is to consider LDAP specifications to be guidelines rather than actual rules. LDAP is still useful for many use cases. However, it is very likely that you need to deviate from the standards to make your solution work. Welcome to the LDAP world!


This document is quite obviously missing some details. Some things may not be entirely correct. If you have corrections or additional details, please contact us. We will gradually correct and update the document. Just please keep your comments factual and pragmatic.

If you think that this is all wrong and that LDAP is perfect, then there is no need to contact us. I hear that opinion way too often. Yet, reality shows a different picture.

If you want to accuse me that I just hate LDAP, there is no need to do that either. Several people did it for you already. Yet, that is far from the truth. I actually like LDAP. I like it very much. I think that LDAP is simple, elegant in its own way, and there are many good things about it. It is very sad that few bad things are completely ruining the experience. Many of these things are easy to fix, even while maintaining almost full compatibility. It is almost unbelievable that there is no will to fix these problems.

You may think that these problems should be fixed in LDAP specifications rather than guiding engineers to violate the specs. In that case you are right! I agree with you completely. You should make your voice heard in LDAP community. I’ve tried to discuss these issues with LDAP community for many years. I tried to explain, I tried to suggest solutions, but to no avail. LDAP community is in deep denial. I’m done trying to persuade people that won’t listen. However, you can give it a try. You may have better luck. Maybe there is still a chance to save LDAP.