So you want to use Active Directory as your Membership Provider for BlogEngine.Net? Well you're in luck, as it is possible to accomplish this task. For more details about using the Active Directory Membership Provider you can read the official MSDN article from Microsoft. For accomplishing this task with BlogEngine then you are at the right place.
Role Provider
BlogEngine uses two default roles, Administrators and Editors, to control access to the management functions. For my initial working model here I decided to continue to use the roles.xml file to control role membership. While not as clean as using Active Directory Security Groups or Local Security Groups, it is better than nothing (I figure role membership on your server shouldn't change all that much after the initial configuration anyway).
Be sure you have the original XML Role Provider settings still in your web.config.
<roleManager defaultProvider="XmlRoleProvider"
enabled="true"
cacheRolesInCookie="true"
cookieName=".BLOGENGINEROLES"> <providers> <clear /> <add name="XmlRoleProvider" type="BlogEngine.Core.Providers.XmlRoleProvider, BlogEngine.Core" description="XML role provider" xmlFileName="~/App_Data/roles.xml"/> </providers> </roleManager>
Edit the ~/app_data/roles.xml file and add your domain users into either the Administrators or Editors role. Don't include any domain information, just the samAccountName.
<?xml version="1.0" encoding="utf-8" standalone="yes"?><roles> <role> <name>Administrators</name> <users> <user>Chris</user> </users> </role> <role> <name>Editors</name> <users /> </role></roles>
Membership Provider
Configure the web.config file to support the Active Directory Membership Provider. To make this happen let's open up ~/web.config and make some changes:
Add an entry into the <connectionStrings> section pointing to your domain controller.
<add name="ADConnectionString" connectionString="LDAP://server.domain.com/DC=domain,DC=com" />
Notice the first part of the LDAP:// syntax specifies the name of the domain controller (server.domain.com). You have a couple of options here. You can specify the Fully Qualified Domain Name as shown in the example; you can specify the relativeDistinguishedNamek (ex. server); you can specify the IP Address of the domain controller (ex. 192.168.1.10); or for more redundancy you can specify just the domain name (ex. domain.com). Which ever you choose just be sure that you can receive a ping response from the entry. If you are unable to ping the server then there's a pretty good chance BlogEngine can't talk to the domain either.
Also, notice that the second part of the syntax indicates the search base (DC=domain,DC=com). If I set the search base to the root of the domain then anyone in the domain would be able to login into BlogEngine. While not a member of Administrators or Editors these unclassified users will still be able to see the Extensions and Change Password menu options in the Administrators panel. Currently I know of two ways to correct this behavior:
- Create a separate OU and add users that should have access to login to BlogEngine into that OU. (admittedly this might not be practical for everyone - perhaps we can see a future change to the BlogEngine core to support readers, editors, and Administrators)
- Edit your theme .ascx file to only display the administration panel to administrators:
<% if (Page.User.IsInRole("Administrators")){ %><div class="box"> <h1>Administration</h1> <uc1:menu ID="Menu1" runat="server" /></div><%} %>
Make your <membership> section look like the following:
<membership defaultProvider="MyADMembershipProvider"> <providers> <add name="MyADMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ADConnectionString" attributeMapUsername="sAMAccountName" enableSearchMethods="true"/> </providers> </membership>
You will notice that I did not configure a username and password for connecting into Active Directory. That's because I am running BlogEngine on a domain member server and the IIS services are running under an application pool using Network Services account. I would strongly recommend that you do the same, as you won't have to manage service account passwords and such. If you must use explicit credentials then you can add connectionUsername and connectionPassword to the MyADMembershipProvider entry with the appropriate information.
Troubleshooting Tips
- Verify that you can connect to the domain controller on port 389 and/or 636 from the BlogEngine server. If you have configured your domain controllers with a certificate then your domain controllers should support TLS (port 636) connections. Magically, BlogEngine will use TLS for LDAP communication if your domain controller supports TLS communication. NOTE: I would strongly recommend that you configure your domain controllers with a certificate.
- Your domain account name and password will travel over the network in the clear unless you configure BlogEngine to support SSL. I would STRONGLY recommend you configure this for your environment. See my previous blog entry for details about this step.
- Role membership doesn't seem to refresh quickly. So when testing moving a user from the Administrators role to the Editors role I would recommend you stop and start the webserver to clear the cache. While testing on Visual Studio I had to stop the Visual Studio Web Services each time I moved a user between roles. Perhaps I am missing something and someone could tell me a better way to make this work better.
- For some reason during my testing I couldn't use the domain\administrator account. Not exactly sure why and I haven't tried to track this issue down, but I side-stepped this issue by adding any other domain account into the Administrators role (Roles.xml) and it worked. Perhaps in the future I will figure out this issue, perhaps someone else will figure it out for me 8-) .
- When I configured the web.config with the setting <trust level="High" /> things didn't work. The error message indicated "Request for the permission of type System.DirectoryServices..... blah blah blah". Now I know there is probably a way to configure an exception for this issue but I figured anyone using Active Directory as their Membership Provider can probably set the trust level to full without too much concern. So make the following configure and things will continue forward: <trust level="Full" />
- Verify you have the connectionString correct. In my testing I had accidentally left off a comma (ex. DC=domaindc=com --> should be --> DC=domain,DC=com) and BlogEngine couldn't find the LDAP base. The exception error you would see "The specified connection string does not represent a valid LDAP adspath".
- During the initial configuration I kept seeing an error indicating "The Active Directory membership provider has not been configured to support search methods". This issue might come up if you forget to add the entry enableSearchMethods="true" in the MyADMembershipProvider section.
If you have any problems just let me know and I will try and help you out!