I received a question recently inquiring whether or not Sitecore is able to use Active Directory Lightweight Directory Services (AD LDS) as a Membership Provider. Not knowing much about AD LDS but having some familiarity with Active Directory, I started performing some research to determine first "what is AD LDS?", and how it might be leveraged for use with Sitecore.
As it turns out, AD LDS was formerly named Active Directory Application Mode (ADAM), but was renamed to AD LDS with the release of Windows Server 2008. AD LDS is a Lightweight Directory Access Protocol (LDAP) directory service that provides flexible support for directory-enabled applications, without the dependencies that are required for Active Directory Domain Services (AD DS). AD LDS provides much of the same functionality as AD DS, but it does not require the deployment of domains or domain controllers. It gives you the capabilities of a multi-master LDAP directory that supports replication without some of the extraneous features of an Active Directory domain controller (domains and forests, Kerberos, trusts, etc.). AD LDS is typically used in situations where you need an LDAP directory but don't want the administration overhead of AD (e.g. authentication for web applications or SQL databases). Its schema can also be fully customized without impacting the AD schema.
AD LDS uses the concept of instances, similar to that of instances in SQL. What this means is one AD LDS server can run multiple AD LDS instances (databases). This is another differentiator from Active Directory: a domain controller can only be a domain controller for one domain. In AD LDS, each instance runs on a different set of ports. The default instance of AD LDS listens on 389 (similar to AD). You can run multiple instances of AD LDS concurrently on a single computer, with an independently managed schema for each AD LDS instance.
Active Directory (AD) typically provides directory services for both the Windows Server operating systems and for directory-enabled applications. For the server operating system, AD stores critical information about the network infrastructure, users and groups, network services, and so on. In this role, AD must adhere to a single schema throughout an entire forest. AD LDS, on the other hand, provides directory services specifically for directory-enabled applications. AD LDS does not require or rely on AD domains or forests. However, in environments where AD exists, AD LDS can use AD for the authentication of Windows security principals.
AD LDS can also be synchronized with AD in the event that you wish to store user data in AD LDS that you can't or don't want to store in AD. Your application will point to the AD LDS instance for this user data, but you probably don't want to manually create all of these users in AD LDS when they already exist in AD. There are tools and methods available to aid with this synchronization that are beyond the scope of this blog post.
See the "Further Reading" section at the end of this post for more resources concerning AD LDS.
I used the following article as an installation guide for AD LDS:
I was able to use the article mostly as written, but here are a few notes about installation for the purposes of this post:
This is where things started to get interesting. Sitecore already has an Active Directory module available for using AD as a membership/role/profile provider. Because AD and AD LDS share many similarities in both schema and function, I had hoped I could just plug in the Sitecore AD module, point it to my LDS instance and all would be well. While I found success using the AD role provider within the Sitecore AD module against LDS, I did encounter some issues when trying to use the AD membership provider against LDS.
Primarily, the issues I encountered revolved around schema differences between AD and LDS. Fortunately, a couple of the issues can be resolved simply through configuration/schema adjustments. The final change, however, requires reverse-engineering and a code change.
After you have AD LDS installed, there are a few basic procedures you need to perform:
This will add the sAMAccountName and ms-DS-User-Account-Control-Computed attributes to the base schema and allow them to be used by user objects in LDS. These attributes are used and referenced by the AD membership provider in the Sitecore AD module. While it is possible to configure the AD module to reference the userDisplayName attribute for usernames instead of the sAMAccountName attribute, the default is sAMAccountName and it doesn't hurt to import the full MS-adamschemaw2k8 schema in the event you'll be synchronizing LDS with AD. Also, the Sitecore AD Role Provider explicitly uses sAMAccountName when retrieving roles and role names.
You need to create a user that is a member of the LDS Administrators role in order to connect to your LDS instance from Sitecore. This user doesn't need to correspond to a Sitecore content author or administrator, the user is essentially only needed for communication with LDS via the membership provider.
Password operations such as setting a password on a new user or resetting a password for an existing user are not allowed, by default, over an unsecured connection (i.e. non-SSL and the connectionProtection attribute on the membership provider definition is set to None). To allow password operations over an unsecured connection, you will need to perform the following steps on the LDS server (courtesy of http://stackoverflow.com/questions/5616080/active-directory-lds-exception). Note: this is only relevant if you use an unsecured (i.e. non-SSL-encrypted) connection.
This will allow you to perform password operations over an unsecured connection.
You can install the Sitecore Active Directory Module normally according to the documentation found on SDN:
After that, pull down the code found here and compile it (note: this code is compiled against the Sitecore AD Module v1.1):
Copy/reference the compiled Sitecore.SecurityExtensions.dll output to your solution.
To use the LDS provider modifications, you'll need to change the membership provider you defined in the web.config as part of the Active Directory module installation. Change the type attribute from LightLDAP.SitecoreADMembershipProvider to Sitecore.SecurityExtensions.LDS.SitecoreLdsMembershipProvider, Sitecore.SecurityExtensions, as shown below:
Important: you'll need to use the credentials of the LDS Administrator user you created earlier within the LDS membership provider configuration element. If you don't, you'll likely see an error logged in the Sitecore log stating you're attempting to use an invalid username or password.
At this point, you should be able to login to the Sitecore desktop and interact with LDS using the User Manager and Role Manager as expected. I should note that my testing of this customized membership provider primarily consisted of standard CRUD operations - in other words, as always exercise caution using this without thorough testing of your own.
Although there is quite a bit of code in the LDS membership provider project, the vast majority of it was copied and pasted from the Sitecore AD module via Reflector. Really, the only change I had to make was to the LightLDAP.SitecoreADMembershipProvider.GetMembershipUserFromSearchResult method. Unfortunately, just to support that minor change, all of the other code in the project is required due to a number of relevant methods and classes being marked as private, internal, or not virtual. Below is a summary of the change I made:
SitecoreLdsMembershipProvider : MembershipProvider
MembershipUser GetMembershipUserFromSearchResult(ISearchResult res)
//if ((DataHelper.GetInt(res, ObjectAttribute.UserAccountControlComputed) & 0x10) != 0)
) & 0x10) != 0)
As you'll notice, the change involved simply renaming the msDS-User-Account-Control-Computed to the proper name. Ideally, this could have been handled through configuration or even if the method was protected virtual instead of private. Alas, Reflector to the rescue!
I should also note that the simplicity of this change belies the volume of effort that was involved in determining why the Sitecore AD module code didn't work with LDS out-of-the-box. I wouldn't wish troubleshooting obscure COM and Active Directory errors upon anyone :)
AD LDS Operations Guide:
Synchronizing AD and AD LDS:
Installing and configuring AD LDS:
Hello Adam, very nice post it was very helpful. But currently I'm having some problems with the user handling. If you can help me please contact me or write to my topic. sdn.sitecore.net/.../ShowPost.aspx Thanks!
Hello there, I have been trying to integrate this solution into a Sitecore 8 project, but with no success. I'm getting a "Could not get pipeline: getFieldValue (domain: )" error. I have tried with the newer version of AD module (1.2) as well as with the old one, Sitecore.Kernel version 7 as well as 8.1, all with no luck. If anyone has the same problem or could help me find a solution, i'd be very thankful