Using Active Directory as the data silo for your membership and role providers makes a lot of sense. Active Directory already contains the bulk of an organizations personnel information such as user names, demographic information, and security role assignments. The addition of the ActiveDirectoryMembershipProvider Class in Microsoft .NET 2.0 now makes enabling Active Directory as your membership provider relatively simple.
I will outline in this post how you can use the ActiveDirectoryMembershipProvider and AuthorizationStoreRoleProvider classes to manage your application's authentication and authorization requirements. I will be assuming you have an ActiveDirectory domain controller setup with your users and security roles, and want to use forms authentication.
Membership
To utilize the ActiveDirectoryMembershipProvider class you will need to configure a connection string that defines an LDAP query that points to your Active Directory and then configure membership to use ActiveDirectoryMembershipProvider.
Example authentication configuration:
<authentication mode="Forms">
<forms cookieless="UseCookies" defaultUrl="Default.aspx" enableCrossAppRedirects="false" loginUrl="Login.aspx" name=".ADAuthCookie" path="/" protection="All" requireSSL="false" slidingExpiration="true" timeout="30"/>
</authentication>
In the configuration above I indicate I am using forms authentication and then define the properties I want to apply to the forms authentication utilized by my application. See ASP.NET Forms Authentication Overview for more information.
Example LDAP connection string:
<connectionStrings>
<add name="ActiveDirectory" connectionString=LDAP://dc1.myorg.com/DC=myorg,DC=com/>
</connectionStrings>
In the configuration above I have defined a connection string named ActiveDirectory that points to a domain controller named dc1 that belongs to the myorg.com domain. You could alternately use the static IP address for your Active Directory domain controller or provide filtering based on an organizational unit (OU) or other properties.
Example membership configuration:
<membership defaultProvider="ADMembershipProvider">
<providers>
<clear/>
<add name="ADMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ActiveDirectory" connectionUsername="userName" connectionPassword="password" attributeMapUsername="sAMAccountName" enableSearchMethods="true" requiresUniqueEmail="true"/>
</providers>
</membership>
In the configuration above I have indicated that I want to use a provider named ADMembershipProvider as my default provider, and then defined this provider with the following properties:
- connectionStringName - This is the name of the LDAP connection string to our our ActiveDirectory domain controller we defined previously.
- connectionUsername - The name of an account that has appropriate permissions to query and possibly update the directory information.
- connectionPassword - The password for the user account.
- attributeMapUsername - In this example I indicate I want to use the Active Directory property called sAMAccountName as the value to map user name login instead of the default which is userPrincipalName.
- If you use sAMAccountName, then users will provide user.name as their login name.
- If you use userPrincipalName (default) then users will provide user.name@domainname as their login name.
- enableSearchMethods - If enabled, then callers can use the search methods available on the provider, but be aware that this can be an expensive call.
- requiresUniqueEmail - If enabled, each user must have a unique email address assigned to them.
Utilizing the membership configuration:
<asp:Login
ID="LoginControl"
runat="server"
EnableTheming="true"
DisplayRememberMe="true"
FailureText="Login attempt has failed."
>
</asp:Login>
After you have wired up Active Directory to the application's membership provider, login controls like <asp:login> will automatically utilize the provider to determine if a user's authentication credentials (user name/password) are valid and then generate a forms authentication ticket.
As you can see, once you have correctly configured your application to use ActiveDirectoryMembershipProvider as your default provider it works very well as a forms authentication provider will very little work on your part. More more information on the information provided above, see How To: Use Forms Authentication with Active Directory in ASP.NET 2.0.
Optional way to create new users in your Active Directory:
Many web applications use the <asp:CreateUserWizard> control to provide a way for users to create a new account for a given web application. You could use the membership provider we defined above, but I prefer to separate my organizations user accounts from accounts created by web users. To enable this I created an organizational unit called Web within my Active Directory tree and then defined the following connection string and provider configuration:
<add name="ActiveDirectoryAnonymous" connectionString=LDAP://dc1.myorg.com/OU=Web,DC=myorg,DC=com/>
<add name="ADMembershipProviderAnonymous" type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ActiveDirectoryAnonymous" connectionUsername="userName" connectionPassword="password" attributeMapUsername="sAMAccountName" enableSearchMethods="false" requiresUniqueEmail="true"/>
You can then create an <asp:CreateUserWizard> control and indicate that it should use the provider named ActiveDirectoryAnonymous.
<asp:CreateUserWizard
ID="CreateUserWizardControl"
runat="server"
MembershipProvider="ADMembershipProviderAnonymous"
>
I have provided an example implementation of how to define a <asp:CreateUserWizard> that uses custom templates to allow a user to provide some basic demographic and then store this information in Active Directory. See CreateUserWizard.aspx.txt and CreateUserWizardControl_CreatedUser.cs.txt for aspx and C# code.
Role Manager
Using Active Directory as your role management provider within an ASP.NET 2.0 application that uses forms authentication is a little trickier to setup. The best solution I have found so far is to use the AuthorizationStoreRoleProvider class. This class utilizes an XML file generated using the AzMan.msc tool to map application specific roles to Windows Active Directory security roles. For example, I could define a role named Administrators that is mapped to the myorg.com/Administrators windows security group. When an authenticated user is added to the myorg.com/Administrators security group in Active Directory, the role provider will return that they belong to the Administrators role I defined and mapped. I like to think of the AuthorizationStoreRoleProvider as the glue that provide a means of mapping application roles to Active Directory security group(s). To use the AuthorizationStoreRoleProvider you will need to define either an LDAP query to an AzMan store on your Active Directory domain or use an XML configuration file, and then configure the provider to use this connection string to handle role management. I choose to use the XML configuration file, as it allows me to deploy the role management configuration information as part of my ASP.NET application. See [How To: Use Authorization Manager (AzMan) with ASP.NET 2.0] for more information.
Example role manager connection string:
<add name="AzMan" connectionString="msxml://~/App_Data/AzMan.xml"/>
Example role manager configuration:
<roleManager enabled="true" defaultProvider="AuthorizationStoreRoleProvider" cacheRolesInCookie="true" cookieProtection="All" cookieTimeout="10">
<providers>
<clear/>
<add name="AuthorizationStoreRoleProvider" type="System.Web.Security.AuthorizationStoreRoleProvider" connectionStringName="AzMan" applicationName="Portal" cacheRefreshInterval="60" scopeName=""/>
</providers>
</roleManager>
In the above configuration we have enabled roles for our application and set the AuthorizationStoreRoleProvider as our default provider. Notice that I have configured the provider to use a connection string called AzMan, and within that authorization manager data store I indicate that I want to use a configured application called Portal. You can run the azman.msc management tool to help you create and edit the authorization manager XML configuration file. See Windows Server 2003 Authorization Manager for more information.
These are the basic steps you will take to create an authorization manager XML file for your application:
- Using azman.msc, create a new XML configuration file.
- Within this XML data store, you define an application.
- Under Definitions --> Role Definitions, you will create the roles you need for your application.
- Under Role Assignments you will assign windows users and/or groups to each role you have defined. This can be a one-to-one mapping to your defined roles (e.g. Administrators role is assigned the domain Administrators security group) or you can assign multiple windows security groups to
- Save and then deploy the XML configuration file to your ASP.NET application, and then configure the connection string and role provider.
At this point your application should now provide authorization information for authenticated users. After a user is authenticated, the role manager will find the windows security groups the user's account belongs to, and then return the roles you defined that have those windows security groups assigned to them. You can use web controls that call the role management provider such as <asp:LoginView> and return content based on authorization like so:
<asp:LoginView ID="LoginViewManagement" runat="server">
<RoleGroups>
<asp:RoleGroup Roles="Administrators, IT Department">
<ContentTemplate>
<asp:HyperLink ID="HyperLinkManagement" runat="server" Target="_parent" Text="Management" NavigateUrl="~/Content/Management" ToolTip="Web site administration/management tools."></asp:HyperLink>
</ContentTemplate>
</asp:RoleGroup>
</RoleGroups>
</asp:LoginView>
Security/Configuration Notes:
Windows Server 2003
- The NETWORK SERVICE account needs to be added to the reader or admin role. Otherwise you get an "access is denied." error.
As you can see, by leveraging the membership and role provider classes in ASP.NET 2.0, you can quickly configure your application to use your Active Directory domain as the single data silo for your authentication and authorization information.