How To: Use Forms Authentication with Active Directory in ASP.NET 2.0

 

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

patterns & practices Developer Center

patterns & practices Developer Center

J.D. Meier, Alex Mackman, Blaine Wastell, Prashant Bansode, Andy Wigley, Kishore Gopalan

Microsoft Corporation

August 2005

Applies To

  • ASP.NET version 2.0
  • Microsoft® Active Directory® directory service

Summary

This How To shows you how to use forms authentication with Microsoft® Active Directory® directory service by using the ActiveDirectoryMembershipProvider. The How To shows you how to configure the provider and create and authenticate users. It also shows you how to enforce the password complexity rules defined by your domain policy and how you can extend your Active Directory schema to store password questions and answers. This allows you to support password resets if users forget their passwords.

Contents

Objectives
Overview
Summary of Steps
Step 1. Create a Web Application with a Logon Page
Step 2. Configure the Web Application for Forms Authentication
Step 3. Configure ASP.NET for Membership
Step 4. Test Forms Authentication
Security Considerations
Additional Considerations
Configuration Attributes
Additional Resources

Objectives

  • Use the ActiveDirectoryMembershipProvider with forms authentication.
  • Manage application user accounts and passwords that are stored in Active Directory.
  • Use the ActiveDirectoryMembershipProvider to enforce password complexity rules.
  • Learn key production considerations when using membership and forms authentication.
  • Learn key security considerations when using membership and forms authentication.

Overview

ASP.NET version 2.0 introduces a membership feature that you can use with forms authentication. The membership feature provides an abstraction for the underlying data store that is used to maintain user credentials, such as user names and passwords. The membership feature includes an API that helps you to easily validate user credentials and manage the user database. Supported membership providers include the SqlMembershipProvider for Microsoft SQL Server™ user store databases and ActiveDirectoryMembershipProvider for Active Directory and Active Directory Application Mode (ADAM) user stores.

This How To shows you how to develop a simple Web site that uses forms authentication with Active Directory. It shows you how to configure the ActiveDirectoryMembershipProvider, create users, authenticate users, and establish password complexity rules. It also shows you how to use questions and answers to support password reset functionality.

Summary of Steps

To use forms authentication with Active Directory in ASP.NET 2.0, complete the following steps:

  • Step 1. Create a Web application with a logon page.
  • Step 2. Configure the Web application for forms authentication.
  • Step 3. Configure ASP.NET for membership.
  • Step 4. Test forms authentication.

Step 1. Create a Web Application with a Logon Page

In this step, you create a simple Web application with a default page and a logon page. Existing users can use the logon page to log on to the site, and new users can use the logon page to register and create new accounts.

To create a Web application with a logon page

  1. Start Microsoft Visual Studio® .NET development system, and then create a new ASP.NET Web site called FormsAuthAD.

  2. Use Solution Explorer to add a new Web form to the site called Login.aspx.

  3. Add a Login control to Login.aspx.

    By default, this control displays a user name field, a password field, and a Remember me next time checkbox. If the user selects this checkbox, a persistent authentication cookie is created and the user's browser stores the cookie on the user's computer.

    For security reasons, you should avoid creating persistent authentication cookies; therefore, disable this feature by setting the DisplayRememberMe property of the Login control to false.

    Note that when a user clicks Login on the Login control, it automatically validates the user by calling the configured membership provider, creates a forms authentication ticket, and then redirects the user back to the page he or she originally requested.

  4. If you are working in a test environment and have a service account with permissions to create new user accounts in Active Directory, add a CreateUserWizard control beneath the Login control so that users can register with your site and create new accounts.

    Note   If you do not have the permissions to create new users, you will need to test authentication with an existing account.

Step 2. Configure the Web Application for Forms Authentication

In this step, you configure your ASP.NET application to use forms authentication.

To configure the Web application for forms authentication

  1. Use Solution Explorer to add a Web.config file to your project.

  2. Locate the <authentication> element, and then change the mode attribute to Forms.

  3. Add the following <forms> element as a child of the <authentication> element, and then set the name and timeout attributes as shown in the following example.

    <authentication mode="Forms">
      <forms
          name=".ADAuthCookie"       
          timeout="10" />
    </authentication>
    
    

    If you only set the mode attribute on the <authentication> element, and omit setting the attribute on the <forms> element, the <forms> configuration will use the default settings. You should configure only those attributes that you want to overwrite. The default settings for forms authentication as defined in the Machine.config.comments file are shown in the following example.

    <forms name=".ASPXAUTH" loginUrl="login.aspx" 
           defaultUrl="default.aspx" protection="All" timeout="30" path="/" 
           requireSSL="false" slidingExpiration="true"
           cookieless="UseDeviceProfile" domain="" 
           enableCrossAppRedirects="false">
      <credentials passwordFormat="SHA1" />
    </forms>
    
    
  4. Add the following <authorization> element beneath the <authentication> element in your Web.config file.

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

    This configuration allows only authenticated users to access the application. The "?" indicates unauthenticated users and the "*" indicates all users. By denying access to unauthenticated users, any requests made by unauthenticated users are redirected to your logon page. The loginUrl attribute on the <forms> element determines the name of the logon page. The default setting of this attribute in Machine.config.comments is "Login.aspx".

Step 3. Configure ASP.NET for Membership

In this step, you configure the Active Directory membership provider by specifying membership settings in your application's Web.config file.

To configure ASP.NET for membership

  1. In the Web.config file, add a connection string similar to the following, and modify it so that it points to your Active Directory users container.

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

    Note   The connection string shown above connects to the user's container within a domain called testdomain.test.com. Update this string to point to the relevant users container within your domain.

  2. Add a <membership> element after your <authorization> element, as shown in the following example.

    <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"
           connectionUsername="testdomain\administrator" 
           connectionPassword="password"/>
      </providers>
     </membership>
    
    

    Make sure that you set the connectionStringName attribute to the same name ("ADConnectionString") you specified earlier in your connectionStrings section.

    Make sure to set the defaultProvider attribute value to MyADMembershipProvider, because this needs to be overwritten. The machine-level default value points to SQLMembershipProvider type, using the local SqlExpress instance. If you do not overwrite this attribute, ASP.NET uses the default provider.

    Note   In the example above, it is assumed that you are working in a test domain and have the password of an administrator account capable of creating new accounts. The administrator name and password must be supplied in plain text. As a result, you should encrypt this configuration section as well as the <connectionStrings> section. For more information, see How To: Encrypt Configuration Sections in ASP.NET 2.0 using DPAPI and How To: Encrypt Configuration Sections in ASP.NET 2.0 using RSA.

For the full list of attribute settings for the ActiveDirectoryMembershipProvider, see the section, "Configuration Attributes."

Connecting to Active Directory

When the ActiveDirectoryMembership provider connects to Active Directory, it uses the account whose credentials are specified on the connectionUsername property (note the lower-case n, which is different from the connectionStringName property). If you specify the connectionUsername property, you must also specify the connectionPassword property, otherwise an exception is thrown.

If you do not specify account credentials, Active Directory uses your ASP.NET Web application's process account.

Note   The service account that you use to connect to Active Directory must have sufficient permissions in Active Directory. If you place your user accounts in an Active Directory organizational unit (OU), you can create and use a service account that has only read, write, and delete access on that OU (and, optionally, reset password privilege).

Step 4. Test Forms Authentication

In this step, you test forms authentication.

Add a Page_Load Event Handler

Add the following code to the Page_Load event handler of your Default.aspx page. This page should be displayed only to authenticated users. To prove that this is the case, the code displays information obtained from the forms authentication ticket that is issued to authenticated users.

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

  FormsIdentity id = (FormsIdentity)User.Identity;
  FormsAuthenticationTicket ticket = id.Ticket;

  Response.Write("<p/>TicketName: " + ticket.Name );
  Response.Write("<br/>Cookie Path: " + ticket.CookiePath);
  Response.Write("<br/>Ticket Expiration: " +  
                  ticket.Expiration.ToString());
  Response.Write("<br/>Expired: " + ticket.Expired.ToString());
  Response.Write("<br/>Persistent: " + ticket.IsPersistent.ToString());
  Response.Write("<br/>IssueDate: " + ticket.IssueDate.ToString());
  Response.Write("<br/>UserData: " + ticket.UserData);
  Response.Write("<br/>Version: " + ticket.Version.ToString());
}
  

Logon as an Existing User

You can test the authentication by logging on with an existing domain account.

To logon as an existing user

  1. Browse to your application's Default.aspx page.

    The earlier configuration of the <authorization> element prevents unauthenticated users from accessing any pages in your application. They are redirected to your Login.aspx page.

  2. Enter valid credentials for an account in your domain, and then click Login.

    The format of the user name depends on the attributeMapUsername attribute of the <membership> element. The default configuration for the ActiveDirectoryMembershipProvider uses User Principal Names (UPNs) for name mapping as shown in the following example.

    attributeMapUsername="userPrincipalName"
    
    

    Because of this, all user names must have the format UserName@DomainName; for example: mary@testdomain.com or steve@testdomain.com.

    You can change the name mapping so that it uses simple user name format by setting the following attribute in the Membership Provider configuration in the Web.config file.

    attributeMapUsername="sAMAccountName"
    
    

    With this configuration, you can use simple user names, for example: Mary or Steve.

Logon as a New User

You can create a new user to test the logon functionality. You will only be able to perform this step if you are working in a test domain environment or if you have configured an administration account that has the privileges to create new users in Active Directory.

To create a new user

  1. Browse to your application's Default.aspx page.

  2. Create a new user with a strong password. The Active Directory membership provider has the following default password rules:

    • The password must be at least seven characters.
    • The password must contain at least one non-alphanumeric character.

    You must supply a password that conforms to either the policy defined by the provider or the policy defined by your Active Directory, whichever is stronger. Active Directory checks the membership configuration first; if that succeeds, then the provider attempts to create the account in Active Directory. If the supplied password does not meet the domain password policy criteria, then the provider will not create the account.

  3. Log on with your new user account. If you log on successfully, you should be redirected back to the Default.aspx page that you initially requested, and the page should display details from the forms authentication ticket.

Note   If you used the default settings when the user account was created, then you will need to supply the user name in the format UserName@DomainName.

In addition to using the CreateUserWizard control, you can create users in the following ways:

  • Use the ASP.NET Web site administration tool, which provides a wizard-like interface for creating new users.
  • Use an ASP.NET Web page that has TextBox controls to obtain the user name and password (and optionally an e-mail address), and then use the Membership. CreateUser method to programmatically create new users.

Security Considerations

Failing to protect authentication tickets is a common vulnerability that can lead to unauthorized spoofing and impersonation, session hijacking, and elevation of privilege. When you use forms authentication, consider the following recommendations to help ensure a secure authentication approach:

  • Restrict the authentication cookie to HTTPS connections. To prevent forms authentication cookies from being captured and tampered with while crossing the network, ensure that you use Secure Sockets Layer (SSL) with all pages that require authenticated access and restrict forms authentication tickets to SSL channels.
  • Partition the site for SSL. This allows you to avoid using SSL for the entire site.
  • Do not persist forms authentication cookies. Do not persist authentication cookies because they are stored in the user's profile on the client computer and can be stolen if an attacker gets physical access to the user's computer.
  • Consider reducing ticket lifetime. Consider reducing the cookie lifetime to reduce the time window in which an attacker can use a captured cookie to gain access to your application with a spoofed identity.
  • Consider using a fixed expiration. In scenarios where you cannot use SSL, consider setting slidingExpiration="false".
  • Enforce strong user management policies. Use and enforce strong passwords for all user accounts to ensure that people cannot guess one another's passwords and to mitigate the risk posed by dictionary attacks.
  • Enforce password complexity rules. Validate passwords entered through the CreateUserWizard control, by setting its PasswordRegularExpression property to an appropriate regular expression. Also configure the membership provider on the server to use the same regular expression.
  • Perform effective data validation on all requests. Perform strict data validation to minimize the possibilities of SQL injection and cross-site scripting.
  • Use distinct cookie names and paths. By ensuring unique cookie names and paths, you prevent possible problems that can occur when hosting multiple applications on the same server.
  • Keep authentication and personalization cookies separate. Keep personalization cookies that contain user-specific preferences and non-sensitive data separate from authentication cookies.
  • Use absolute URLs for navigation. This is to avoid potential issues caused by redirecting from HTTP to HTTPS pages.

For more information about these additional security considerations, see How To: Protect Forms Authentication in ASP.NET 2.0.

Additional Considerations

When you use forms authentication with Active Directory, consider using the following additional security mechanisms:

  • Password reset
  • Account lockout

Password Reset

The ActiveDirectoryMembershipProvider class supports password reset security by requiring the user to answer a security question. The user provides this question and its answer when he or she creates the account.

To enable password reset

  1. Extend your Active Directory schema to add new attributes to the built-in User class.

    Add the following two new attributes to store the question and answer:

    • A single-value attribute of type string to hold a password question.
    • A single-value attribute of type string to hold a password answer.

    Add the following three new attributes to store tracking data that will be used to manage account lockout:

    • A single-value attribute of type integer to track the failed answer count.
    • A single-value attribute of type Large integer/interval to hold the last time at which the user supplied an invalid answer while attempting to reset the password.
    • A single-value attribute of type Large integer/interval to hold the time at which the account was locked out because the user provided several bad password answers in succession. Note that the account is not locked out with Active Directory; therefore, the user could still log on to Windows with the account. However, the ActiveDirectoryMembershipProvider treats the account as locked out, so that the user cannot log on to an application that uses the provider until the lockout duration elapses.

    Note   To edit the Active Directory schema on Windows Server 2003, use Regsvr32.exe to register schmmgmt.dll, and then load the Active Directory Schema Microsoft Management Console (MMC) snap-in.

    You can use the ADSIEdit MMC snap-in to view and edit attribute values within Active Directory.

  2. Set the following configuration attributes by using the <add> element for your <providers> section in the Web.config file:

    • Set enablePasswordReset to true.
    • Set requiresQuestionAndAnswer to true.
    • Set attributeMapPasswordQuestion to the name of the Active Directory attribute on the User class that contains the password security question.
    • Set attributeMapPasswordAnswer to the name of the Active Directory attribute on the User class that contains the answer to the password security question.
    • Set attributeMapFailedPasswordAnswerCount to the name of the Active Directory attribute on the User class that tracks the number of failed answers to the password security question.
    • Set attributeMapFailedPasswordAnswerTime to the name of the Active Directory attribute on the User class that tracks the times at which the user enters an incorrect answer to the password security question.
    • Set attributeMapFailedPasswordAnswerLockoutTime to the name of the Active Directory attribute on the User class that tracks how long the account is locked out.

    Note   You cannot reset passwords unless the credentials that are used to connect to Active Directory have either Domain Administrator rights (not recommended) or the Reset password privilege.

    Your provider configuration to support password resets should be similar to the following example.

    <add
      name="MyADMembershipProvider"
      type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, 
            Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
      connectionStringName="ADConnectionString"
      connectionUsername="dc\administrator" 
      connectionPassword="P@ssw0rd"
      attributeMapUsername="sAMAccountName"
      enablePasswordReset="true"
      requiresQuestionAndAnswer="true"
      attributeMapPasswordQuestion="passwordQuestion"
      attributeMapPasswordAnswer="passwordAnswer"
      attributeMapFailedPasswordAnswerCount="badPasswordAnswerCount" 
      attributeMapFailedPasswordAnswerTime="badPasswordAnswerTime"
      attributeMapFailedPasswordAnswerLockoutTime=
            "badPasswordAnswerLockoutTime" 
      requiresUniqueEmail="true" />
    
    

    Note   You should also set the optional attribute requiresUniqueEmail="true", to ensure that users have unique e-mail IDs.

  3. Set the PasswordRecoveryText and PasswordRecoveryURL on your Login control. Set the URL to a page that contains a PasswordRecovery control.

    If a user forgets a password, he or she can click the forgotten password link on the Login control and then enter a user name. The PasswordRecovery control then prompts the user with the predetermined question. When the user submits the correct answer, the ActiveDirectoryMembershipProvider resets the user's password to a randomly created password value of an appropriate strength, and then sends the new password in an e-mail message to the user.

    Note   For an e-mail message to be sent successfully, the user must have supplied a valid e-mail address when the account was created, and the <mailSettings> configuration within the <system.net> section of the Machine.config file must be appropriately configured with the details of the SMTP server.

Account Lockout

To mitigate the risks posed by password guessing attacks, the ActiveDirectoryMembershipProvider supports account lockout and account lockout time periods. However, it does so separately from Active Directory. The ActiveDirectoryMembershipProvider tracks the number of failed password attempts and failed password answer attempts in a specified time period, and will lock out an account if a user exceeds the configured thresholds.

Note   If the ActiveDirectoryMembershipProvider locks out an account, it does not appear as locked out in Active Directory. As a result, a user could still log on to Windows with an Active Directory account, but not be able to log on through any application that uses the ActiveDirectoryMembershipProvider.

You can configure account lockout policy with the following two provider attributes:

  • maxInvalidPasswordAttempts. This attribute defines the number of failed password attempts or failed password answers that are allowed before the provider locks out a user's account. When the number of failed attempts equals the value set in this attribute, the provider treats the user's account as locked out. The default value is 5.
  • passwordAttemptWindow. This attribute defines how long the provider tracks failed password attempts and password answer attempts, in minutes. The default value is 10.

If you use the defaults, the provider will treat the account as locked out if there are 5 failed log on attempts or 5 failed password answer attempts within 10 minutes.,

Unlocking an Account

To unlock a locked account, you can either call the UnlockUser method on the MembershipUser object, or you can wait until the time limit specified by the attributeMapFailedPasswordAnswerLockoutTime attribute elapses. After that amount of time has passed, the account automatically unlocks and is available for log on again.

Configuration Attributes

The ActiveDirectoryMembershipProvider has the following attributes, which you can optionally override in your Web.config configuration.

Table 1: ActiveDirectoryMembershipProvider Attributes and Default Values

Attribute Default Value Description
connectionProtection Secure Specifies the transport layer security options that are used when opening connections to the directory. You can set this attribute to either Secure or None. If you set it to Secure, the ActiveDirectoryMembershipProvider attempts to connect to Active Directory by using SSL. If SSL fails, the provider makes a second connection attempt by using sign-and-seal. If both attempts fail, a ProviderException exception is generated.

This attribute supports both process credentials and explicit credentials.

enablePasswordReset true Specifies whether the provider is configured to allow users to reset their passwords.
enableSearchMethods false Allows an administrator to set whether or not search-oriented methods can be called in the provider instance.
requiresQuestionAndAnswer false Specifies whether or not a security question and answer need to be provided.
applicationName / Specifies the name of the application that is using the membership provider.
requiresUniqueEmail false Specifies whether a unique e-mail address is required from the user when creating an account.
maxInvalidPasswordAttempts 5 Specifies the number of failed logon attempts a user is allowed before the user is locked out.
passwordAttemptWindow 10 Specifies the number of minutes during which a user is allowed to make logon attempts before he or she is locked out.
passwordAnswerAttemptLockout
Duration
30 Specifies the length of time a user is locked out after exceeding the maximum number of invalid password attempts.
minRequiredPasswordLength 7 Specifies the minimum acceptable length for a password, in characters.
minRequiredNonalphanumeric
Characters
1 Specifies the minimum number of non-alphanumeric characters that a password must contain.
passwordStrengthRegular
Expression
"" Specifies a regular expression that can be used to create a strong password. By default, a strong password should contain at least seven characters, including one non-alphanumeric character.
attributeMapUsername userPrincipal
Name
Defines the mapping from a property on a MembershipUser object to an attribute within Active Directory. This attribute defines how user names must be supplied when users create new accounts or log on through the CreateUserWizard and Login controls.
attributeMapEmail mail Defines the mapping from a property on a MembershipUser object to an attribute within Active Directory. This attribute holds the user's e-mail address.
attributeMapPasswordQuestion   Defines the mapping from a property on a MembershipUser object to an attribute within Active Directory. This attribute holds a question that the user must answer correctly to reset his or her password. This attribute is populated by the CreateUserWizard control when the account is created.
attributeMapPasswordAnswer   Defines the mapping from a property on a MembershipUser object to an attribute within Active Directory. This attribute holds the answer to the password security question. This attribute is populated by the CreateUserWizard control when the account is created.
attributeMapFailedPassword
AnswerCount
  Defines the mapping from a property on a MembershipUser object to an attribute within Active Directory. This attribute holds the maximum number of times that a user can supply an incorrect password answer before the account is locked out.
attributeMapFailedPassword
AnswerTime
  Defines the mapping from a property on a MembershipUser object to an attribute within Active Directory. This attribute holds the length of time in minutes during which Active Directory tracks password answers.
attributeMapFailedPassword
AnswerLockoutTime
  Defines the mapping from a property on a MembershipUser object to an attribute within Active Directory. This attribute holds the length of time in minutes that an account will be locked out if the user supplies a succession of incorrect answers.

Additional Resources

Feedback

Provide feedback by using either a Wiki or e-mail:

We are particularly interested in feedback regarding the following:

  • Technical issues specific to recommendations
  • Usefulness and usability issues

Technical Support

Technical support for the Microsoft products and technologies referenced in this guidance is provided by Microsoft Support Services. For product support information, please visit the Microsoft Product Support Web site at https://support.microsoft.com.

Community and Newsgroups

Community support is provided in the forums and newsgroups:

To get the most benefit, find the newsgroup that corresponds to your technology or problem. For example, if you have a problem with ASP.NET security features, you would use the ASP.NET Security forum.

Contributors and Reviewers

  • External Contributors and Reviewers: Jason Taylor, Security Innovation; Rudolph Araujo, Foundstone Professional Services
  • Microsoft Consulting Services and PSS Contributors and Reviewers: Adam Semel, Tom Christian, Wade Mascia
  • Microsoft Product Group Contributors and Reviewers: Stefan Schackow
  • Test team: Larry Brader, Microsoft Corporation; Nadupalli Venkata Surya Sateesh, Sivanthapatham Shanmugasundaram, Infosys Technologies Ltd.
  • Edit team: Nelly Delgado, Microsoft Corporation; Tina Burden, TinaTech Inc.
  • Release Management: Sanjeev Garg, Microsoft Corporation

patterns & practices Developer Center

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.