Active Directory for BlogEngine.NET Membership Provider

by chris 1/16/2008 4:35:00 PM

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: 

  1. 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)
  2. Edit your theme .ascx file to only display the administration panel to administrators:
  3. 	<% 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!

kick it on DotNetKicks.com

Related posts

Comments

1/17/2008 1:52:17 PM

avalongirl

It works! Thank you very much! I really appreciate it. Btw, I comment out the user page from web.sitemap as it causes exception and no need to have it in this case.

I wonder if you think the Windows Authentication will work too. No need to find out though. I am just curious as I wish this kind of configuration could be easily implemented by configuration.

avalongirl gb

1/18/2008 4:14:28 AM

Steve

Your code/configuration works great. Issue seems to be within the AD Membership provider itself.
The HttpContext.Current.User.Identity.Name property returns user as "DOMAIN\user", but the AD provider (and LDAP) returns the Username as just "user"; Thus searching the membership list without removing "DOMAIN\" fails. The underlying code in M$ AD provider (For GetUser() in particular) issues: "return GetUser (HttpContext.Current.User.Identity.Name, true);". This also seems to have an effect on BlogEngine functions like "PreSelectAuthor(Page.User.Identity.Name)", in that it doesn't match any of the members.
I have been searching Internet, but so far have been unable to find any solutions to these that don;t involve adding extra code to strip the Domain prior to calling the membership functions.

Steve gb

3/19/2008 6:59:59 AM

91smw

very good....

91smw cn

5/7/2008 1:17:42 AM

Fraenzy

Hi,

i have problems with the ascx-File. I'll get an error if I put your "if UserIsInRole.."-Line into my theme(standard)-file.
Which file and with format is it?

Fraenzy

Add comment


(Will show your Gravatar icon)  

  Country flag

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



Powered by BlogEngine.NET Theme by Mads Kristensen © 2008 Chris Blankenship Sign in
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway
Page Updated Thursday, May 01, 2008

Welcome to my blog

Welcome to my site

Don't sweat the petty stuff...
...and don't pet the sweaty stuff



Subscribe to comments feed Recent comments exp/col

View Chris Blankenship's profile on LinkedIn   DSCODUC on Technorati

check out my neighbors in meatspace  

Stop Spam Harvesters, Join Project Honey Pot   This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License