Frank Wang's inspirations on .NET

IEnumerable<Inspiration> inspirations = from i in DataContext.Inspirations where i.Sharable == true select i

Forms Authentication with Active Directory in ASP.NET 2.0

Sunday, May 18, 2008 12:59 AM

The Membership API is new to ASP.NET 2.0. It provides you with a full-fledged infrastructure for managing and authenticating users of your applications. ASP.NET 2.0 shipped two Membership providers, SQL Server and Active Directory. While plenty of articles and blog posts have been published on how to use the SQL Server Membership provider, very few have been done for the Active Directory Membership provider. I was recently leading an enterprise web site project that required the Active Directory authentication. I just thought it might be interesting to share with you a few bullet points of using Active Directory Membership provider in ASP.NET 2.0.

In this blog post, we will implement the AD authentication in an ASP.NET web site by completing the following four steps.

  • Create a web app with a login page
  • Configure the web app to use forms authentication
  • Add the ActiveDirectoryMemebershipProvider into the web app
  • Manager users with ActiveDirectoryMemebershipProvider

Create a web app with a login page

Open Visual Studio 2008, create a new Web Site named FormsAuthAD. After the web site is created, add a new web form named "Login.aspx", and then place a Login control onto the form.

<asp:Login ID="Login1" runat="server" BackColor="#F7F6F3" BorderColor="#E6E2D8" 
            BorderPadding="4" BorderStyle="Solid" BorderWidth="1px" Font-Names="Verdana" 
            Font-Size="Small" ForeColor="#333333" Height="130px" 
            onloginerror="Login1_LoginError" Width="303px">
          <TextBoxStyle Font-Size="Small" />
          <LoginButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="Solid" 
              BorderWidth="1px" Font-Names="Verdana" Font-Size="Small" ForeColor="#284775" />
          <InstructionTextStyle Font-Italic="True" ForeColor="Black" />
          <TitleTextStyle BackColor="#5D7B9D" Font-Bold="True" Font-Size="Small" 
              ForeColor="White" />
        </asp:Login>

We don't need to configure anything for the Login control.

Configure the web app to use forms authentication

If the web.config file was not created, go ahead and add it to the project. Locate the <authentication> element in the web.config file, and then change the mode attribute to Forms. Add the <forms> element as the child of the <authentication> element, set the loginUrl, defaultUrl, name and the timeout attributes as shown in the following example.

<authentication mode="Forms">
            <forms name=".ADAuthCookie" timeout="10" 
                    loginUrl="Login.aspx" defaultUrl="Default.aspx">
            </forms>
        </authentication>

The <authorization> element is also required to make the forms authentication work. Add the following <authorization> element beneath the <authentication> element in the web.config file.

<authorization>
   <deny users="?"/>
   <allow users="*"/>
</authorization>

What's happening here is we are allowing only authenticated users to access the app. The "?" indicates unauthenticated users and the "*" indicates all users.

Add the ActiveDirectoryMemebershipProvider

The ActiveDirectoryMemebershipProvider can be configured by specifying memebership settings in the web.config file. First of all, we need to add a connection string that points to the Active Directory user container. The domain name of my home lab is called dotnetinspirations.com, so my connection string looks like this:

<connectionStrings>
    <add name="ADConnectionString" connectionString="LDAP://dotnetinspirations.com/CN=Users,DC=dotnetinspirations,DC=com"/>
</connectionStrings>

Now we need to add the ActiveDirectoryMemebershipProvider to use the connection string defined above. Add a <membership> element after the <authorization> element as shown below.

<membership defaultProvider="DomainLoginMembershipProvider">
   <providers>
     <add name="DomainLoginMembershipProvider" 
          type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0,Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" 
          connectionStringName="ADConnectionString" 
          connectionUsername="dotnetinspiration.com\administrator" connectionPassword="youradminpassword"/>
   </providers>
 </membership>

Note the connectionStringName is set to the name "ADConnectionString" we specified earlier. An interesting point here is we overwrote the defaultProvider attribute to "DomainLoginMemebershipProvider", which is defined in the <providers> element. We have to overwrite this attribute because the machine-level default MembershipProvider points to SQLMembershipProvider, using the localhost\SQLExpress instance, and that's the default provider used by ASP.NET.

In this example, I have all the control over my own dotnetinspiration.com domain and I logged into the Active Directory as the administrator. If you are running this application in a less flexible environment, you need to obtain an domain account that has sufficient permissions in Active Directory. If you do not specify account credentials (connectionStringName and connectionPassword), Active Directory uses your ASP.NET web app's process account, which typically has fairly low priviledges, and you may not be able to test all the features of the application. 

Up to this point, we are ready to test the Active Directory authentication. We will just add a quick line of code in the default.aspx page to display the authenticated user's identity. This should be done in the Page_Load event handler of the default.aspx page.

protected void Page_Load(object sender, EventArgs e)
{
  Response.Write("Hello, " + Server.HtmlEncode(User.Identity.Name));
}

Run the web site and log in using any existing account on your domain. If the the login is successful, you will be redirected to the default.aspx page, which displays the name of the logged in user. Otherwise, the login control will automatically display login failure message to you.

Manager users with ActiveDirectoryMemebershipProvider

The ActiveDirectoryMemebershipProvider not only provides you with you the capability of authenticating users without writing any code but also allows you to conveniently manage users in ASP.NET as if you were working on the Active Directory. We will demonstrate this by creating a new web form for adding new users. From the Solution Explorer, add a new page called CreateNewUser.aspx, add a CreateUserWizard control to the form once it is generated.

<asp:CreateUserWizard ID="CreateUserWizard1" runat="server" BackColor="#F7F6F3" 
    BorderColor="#E6E2D8" BorderStyle="Solid" BorderWidth="1px" 
    Font-Names="Verdana" Font-Size="Small">
    <SideBarStyle BackColor="#5D7B9D" BorderWidth="0px" Font-Size="0.9em" 
        VerticalAlign="Top" />
    <SideBarButtonStyle BorderWidth="0px" Font-Names="Verdana" ForeColor="White" />
    <ContinueButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" 
        BorderStyle="Solid" BorderWidth="1px" Font-Names="Verdana" 
        ForeColor="#284775" />
    <NavigationButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" 
        BorderStyle="Solid" BorderWidth="1px" Font-Names="Verdana" 
        ForeColor="#284775" />
    <HeaderStyle BackColor="#5D7B9D" BorderStyle="Solid" Font-Bold="True" 
        Font-Size="0.9em" ForeColor="White" HorizontalAlign="Center" />
    <CreateUserButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" 
        BorderStyle="Solid" BorderWidth="1px" Font-Names="Verdana" 
        ForeColor="#284775" />
    <TitleTextStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
    <StepStyle BorderWidth="0px" />
   <WizardSteps>
       <asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
       </asp:CreateUserWizardStep>
       <asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
       </asp:CompleteWizardStep>
   </WizardSteps>
</asp:CreateUserWizard>

Just like the Login control, nothing needs to be configured for the CreateUserWizard control to work. The ASP.NET reads the web.config file during runtime and it becomes aware of the underlying data source for managing users.

Run the web site again, log into the site this time with a privileged account (we need to be able to create new users). In the browser's address bar, replace default.aspx with CreateNewUser.aspx. Follow the wizard and create a brand new user. Log into the web site one more time with this new account.

The source code for the example can be downloaded here.


Feedback

# re: Forms Authentication with Active Directory in ASP.NET 2.0

Nice article. You're right, there's not so much info on AD Auth. Nice intro, although how straightforward is it to, say, use the AD permissions to show specific links in a page?

I.e. I have a page of links. I want to show or hide various links (and allow/deny certain actions) based on AD permissions. (something akin to ASP.NET Site-Map Security Trimming)

Any info/links/examples? 5/28/2008 4:54 AM | Mark

# re: Forms Authentication with Active Directory in ASP.NET 2.0

hai te4sting page 6/29/2008 2:15 AM | satish

# re: Forms Authentication with Active Directory in ASP.NET 2.0

Hi.

I just like to create a login page for one AD User. So just one AD User should be able to login. How can this be done ? What's the easiest way to do it ?

thx

Rudi 7/15/2008 9:26 AM | Rudi

# re: Forms Authentication with Active Directory in ASP.NET 2.0

Hi Rudi,

I would say the easiest way to do it is use the same AD login and check the user's credential in the OnLoggingIn event.

Hope this helps.

Frank 7/15/2008 10:31 AM | Frank Wang

# re: Forms Authentication with Active Directory in ASP.NET 2.0

hi Frank!

First of all thx. What do you mean with the same AD login. You mean I just should check in the OnLoggingIn event if the correct Username is supplied [without password validation] ? The other problem I'm facing right know is that I don't know the connectionstring in advance because the site is deployed on many servers and I don't know these domains in advance. Is there a way to construct the connectionstring somehow dynamically !

thx in advance

Rudi 7/15/2008 12:13 PM | Rudi

# re: Forms Authentication with Active Directory in ASP.NET 2.0

Hai

Very nice article! I was also gotten this far (with a lot of trial and error). One question though: what do you mean by "if you are running this application in a less flexible environment, you need to obtain an domain account that has sufficient permissions in Active Directory."

What is sufficient permissions? What kind of permissions are needed to authenticate a user?

Thanks! 8/6/2008 1:13 AM | Pieter-Jan

# re: Forms Authentication with Active Directory in ASP.NET 2.0

Hi Pieter-Jan,

The user that logs into the domain controller needs to have permissions for querying Active Directory to be able to authenticate users. Consult your network administrator, who should be able to create an account with sufficient priviledges.

Frank
8/6/2008 3:19 PM | Frank Wang

# re: Forms Authentication with Active Directory in ASP.NET 2.0

Hi Frank;
Thanks about the article. I can`t use the sample code, and the membership specified here isn't working for me. I found an alternate membership specification:

<add name="MembershipADProvider"
type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="ADConnectionString"
attributeMapUsername="sAMAccountName"
enableSearchMethods="true"/>

...but users can't log-in with domain\user user-name. Only with user. Why this happens?. How can i set the membership or connection string in order to get this working?. any suggestion?.

My conn. string :

<add name="ADConnectionString" connectionString="LDAP://ip/OU=my bu,DC=companyname,DC=net"/>

Thanks in advance. 8/18/2008 6:45 AM | Alex Segovia

Post a comment





 

Please add 3 and 4 and type the answer here: