Return to ASPNET2SecurityHowTos


How To: Use Forms Authentication with SQL Server in ASP.NET 2.0

J.D. Meier, Alex Mackman, Blaine Wastell, Prashant Bansode, Andy Wigley
Microsoft Corporation
May 2005

Applies To

* ASP.NET 2.0
* SQL Server 2000


Summary

This How To explains how you can use Forms authentication with the SQL Server membership provider. Forms authentication with SQL Server is most applicable in situations where users of your application are not part of your Windows domain, and as a result, they do not have Active Directory accounts. This How To explains how to create and use the SQL Server membership database, configure the SQL Server membership provider, and set password complexity rules.

Contents

* Overview
* Summary of Steps
* Step 1: Create a Web Application with a Login Page
* Step 2: Configure the Web Application for Forms Authentication
* Step 3: Configure ASP.NET for Membership
* Step 4: Test the Forms Authentication
* Additional Considerations
* Additional Resources

Overview

ASP.NET 2.0 introduces a Membership feature, which you can use with Forms authentication. The Membership feature provides an abstraction for the underlying data store used to maintain user credentials (such as user names and passwords), and provides an API that allows you to easily validate user credentials and manage the user database. Supported membership providers include SQL Server and Active Directory.
This How To shows you how to develop a simple Web site that uses Forms authentication with the SQL Server Membership provider. This provider uses an underlying SQL Server database as its user store.

Summary of Steps

To develop a simple application that uses Forms authentication with the SQL Server membership provider, perform the following steps:
* Step 1: Create a Web application with a login page.
* Step 2: Configure the Web application for Forms authentication.
* Step 3: Configure ASP.NET for membership.
* Step 4: Test the Forms authentication.

Step 1: Create a Web Application with a Login Page

In this step, you create a simple Web application with a default page and a login page. The login page allows existing users to login and new users to register by creating new accounts.

To create a Web application with a login page

1. Start Visual Studio .NET and create a new ASP.NET Web site called FormsAuthSQL.
2. Use Solution Explorer to add a new Web form called Login.aspx to the site.
3. Add a Login control to Login.aspx.

By default, this control displays user name and password fields 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 it on the user's hard disk.
To prevent an attacker from stealing an authentication cookie from the client's computer, you should generally not create persistent authentication cookies. To disable this feature, set 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 originally requested page. It executes code similar to the following example:

		 if [(Membership.ValidateUser(username,] password))
		 {
		  // User has supplied valid credentials
	

		  // In the following method call, the second Boolean parameter 
		  // determines whether or not a persistent authentication cookie
		  // is created
	

		  [FormsAuthentication.RedirectFromLoginPage(username,]
		                                            [rememberMeIsChecked);]
		 }
	

4. Add a CreateUserWizard control beneath the Login control to allow new users to register with your site and create new accounts.

Step 2: Configure the Web Application for Forms Authentication

In this step, you configure the 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 change the mode attribute to "Forms".
3. Add the following <forms> element as a child of the <authentication> element, and set the name and timeout attributes as follows.

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

If you just set the mode attribute of the <authentication> element and omit the <forms> element, default settings are used for the <forms> configuration. You should configure only those attributes that you need to overwrite. The default settings for Forms authentication as defined in the Machine.config.comments file are shown here:

		 <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 under the <authentication> element in the Web.config file. This allows all authenticated users to access your Web site.

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

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

Step 3: Configure ASP.NET for Membership

In this step, you configure the SQL Server membership provider by performing the following actions:
  • Create a user store database.
  • Grant database access to your Web application account.
  • Configure ASP.NET membership settings.

Create a User Store Database

The SQL Server Membership provider stores user information in a SQL Server database. You can create your SQL Server user store manually by using Aspnetregsql.exe from the command line. Alternatively, you can run Aspnetregsql.exe in Wizard mode or use the ASP.NET Configuration tool available from the Website menu in Visual Studio .NET 2005.

To create the user store database

* Use Aspnet_regsql.exe to create the membership database. From a Visual Studio 2005 Command Prompt, run the following command.

		 aspnet_regsql -S (local) -E -A m
	

-S specifies the server, which is (local) in this example.
-E specifies to use Windows authentication to connect to SQL Server.
-A m specifies to add only the membership feature. For simple authentication against a SQL Server user store, only the membership feature is required.
For a complete list of the commands, run Aspnet_regsql /?.

Expected Results

If the Aspnetdb database does not exist, then two database files are created:
* Aspnetdb.mdf
* Aspnetdb_log.LDF

Within the Aspnetdb database, the following tables are created if they do not exist:
* aspnet_Applications
* aspnet_Membership
* aspnet_SchemaVersions
* aspnet_Users

Grant Database Access to the Web Application Account

Your Web application process account requires access to the Aspnetdb database. If you run your application under IIS 6 on Windows Server 2003, the NT AUTHORITY\Network Service account is used by default to run Web applications.

To grant database access

1. Create a SQL Server login for NT AUTHORITY\Network Service.
2. Grant the login access to the Aspnetdb database by creating a database user.
3. Add the user to the aspnetMembershipFullAccess database role.

You can perform these steps by using Enterprise Manager or you can run the following script in SQL Query Analyzer.

		 --Create a SQL Server login for the Network Service account
		 sp_grantlogin 'NT AUTHORITY\Network Service'
	

		 --Grant the login access to the membership database
		 USE aspnetdb
		 GO
		 sp_grantdbaccess 'NT AUTHORITY\Network Service', 'Network Service'
	

		 -- Add user to database role
		 USE aspnetdb
		 GO
		 sp_addrolemember 'aspnet_Membership_FullAccess', 'Network Service'
	

Configure ASP.NET Membership Settings

In this step, you specify membership settings for the Web site.

To configure the Membership settings

1. In the Web.config file, add a connection string similar to the following to point to your membership database.

		 <connectionStrings>
		  <add name="MyLocalSQLServer"
		       connectionString="Initial Catalog=aspnetdb;data source=localhost;Integrated Security=SSPI;" />
		 </connectionStrings>
	

In this case, MyLocalSQLServer is the name you will use for this connection. Set the connectionString attribute to the membership database you created earlier.
2. Add a <membership> element after the <authorization> element as shown in the following example. Note the use of the <clear/> element. This prevents the default provider from being loaded and then never used.

		 <membership defaultProvider="MySqlMembershipProvider" >
		  <providers>
		    <clear/>
		    <add name="MySqlMembershipProvider"
		         connectionStringName="MyLocalSQLServer"
		         applicationName="MyAppName"
		         type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
		  </providers>
		 </membership>
	

Make sure you set the connectionStringName attribute to the same name ("MyLocalSQLServer") you specified earlier in the connectionStrings section. Also set the applicationName attribute to a unique value representing the application. User details are organized by application name within the membership database.

Note: You must set the defaultProvider attribute of the <membership> element to point to the provider definition. The login and related controls use this attribute to determine which property to use. While you can also set the MembershipProvider property of the login controls, it is good practice to set the defaultProvider attribute.

Step 4: Test the 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 only be displayed to authenticated users. To prove that this is the case, the code displays information obtained from the Forms authentication ticket 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());]
		 }
	

Create a New User

In this step, you create a new user to test the login functionality.

To create a new 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 the application and redirects you to the Login.aspx page.
2. Create a new user with a strong password. The default rules applied by the SQL membership provider for the password are as follows:
* The password must be at least 7 characters long.
* The password must contain at least 1 non-alphanumeric character.

3. Login with your new user account. If successful, you should be redirected to the Default.aspx page that you initially requested, and details from the Forms authentication ticket should be displayed.

Additional Considerations

When using Forms authentication, also consider the following:
* Restrict the authentication cookie to HTTPS connections.
* Partition the site for Secure Socket Layer (SSL).
* Consider using a fixed expiration.
* Do not persist authentication cookies.
* Enforce password complexity rules.

Restrict the Authentication Cookie to HTTPS Connections

If you use cookie-based Forms authentication, you can prevent cookies from being captured and tampered with while crossing the network by using SSL with all pages that require authenticated access and restricting Forms authentication tickets to SSL channels by setting the secure cookie property.

To restrict Forms authentication tickets to SSL channels

* Set this cookie property by setting requireSSL="true" on the <forms> element as shown here.

		 <authentication mode="Forms">
		  <forms
		      name="SqlAuthCookie"       
		      timeout="10" 
		      requireSSL="true" />
		 </authentication>
	

By setting requireSSL="true" you set the secure cookie property that determines whether or not browsers should send the cookie back to the server. With the secure property set, the browser sends the cookie only to a secure page that is requested using an HTTPS URL.

Partition the Site for Secure Socket Layer (SSL)

To avoid having to use SSL across your entire site, structure your Web site so that the secure pages that require authenticated access are placed in a subdirectory that is separate from the anonymously accessible pages. The following example shows this approach.

{Insert figure: SolutionExplorerFormsAuthSSL.gif}
Figure 1
Visual Studio.NET Solution Explorer showing a partitioned Web site
In this example, secure pages — including the application's login page — are placed in the Secure folder beneath the application's virtual root directory. In IIS, you configure the Secure folder to require SSL. This sets the AccessSSL=true attribute for the folder in the IIS metabase. Requests for pages in the secured folders are successful only if HTTPS is used for the request URL.
Use the <authorization> element to ensure that only authenticated users can access secure pages. Place this element beneath the closing </system.web> tag, as shown here:

		 <!-- The secure folder is for authenticated and SSL access only. -->
		 <location path="Secure" >
		  <system.web>
		    <authorization>
		      <deny users="?" />
		    </authorization>
		  </system.web>
		 </location>
	

Additionally, the following configuration ensures that unauthenticated users are allowed to access pages in the application's root directory. Place this configuration in the main <system.web> element.

		 <system.web>
		  <!-- The virtual directory root folder contains general pages.
		       Unauthenticated users can view them and they do not need 
		       to be secured with SSL. -->
		  <authorization>
		    <allow users="*" />
		  </authorization>
		 </system.web>
	


Note: If you use this type of site structure, your application must not rely on the user’s identity on the non-SSL pages. In the above configuration, no Forms authentication ticket is sent for requests for non-SSL pages. As a result, the user is considered anonymous. This has implications for related features such as Personalization which require the user name.

Consider Using a Fixed Expiration

Consider setting slidingExpiration="false" for the <forms> element to fix the cookie expiration, rather than resetting the expiration period after each Web request. This is particularly important if you are not using SSL to protect the cookie.

Do Not Persist Authentication Cookies

Do not persist authentication cookies because they are stored in the user's profile and can be stolen if an attacker gets physical access to the user's computer. To ensure a non-persistent cookie, set the DisplayRememberMe property of the Login control to false.

Enforce Password Complexity Rules

The membership provider that the CreateUserWizard and Login controls use determines password complexity requirements. For example, by default, the SQL Membership provider requires passwords of at least 7 characters in length with at least 1 non-alphanumeric character.

Configuring Provider Enforced Strong Passwords

To configure the precise password complexity rules enforced by your provider, you can set the following additional attributes.
* passwordStrengthRegularExpression. The default is "".
* minRequiredPasswordLength. The default is 7.
* minRequiredNonalphanumericCharacters. The default is 1.

Note: The default values shown are for the SQL Server membership provider.

The following configuration supplies a custom regular expression to constrain the passwords used by the membership provider.

		 <membership defaultProvider="MySqlMembershipProvider">
		  <providers>
		    <add name="MySqlMembershipProvider" 
		         connectionStringName="MyLocalSQLServer" 
		         applicationName="MyAppName"
		         [passwordStrengthRegularExpression=]
		                    "^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$" 
		         type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
		  </providers>
		 </membership>
	

The regular expression in the above fragment constrains the password to 8 – 10 characters. It must also contain a combination of uppercase, lowercase, and numeric characters, with no special characters. The (.\d) refers to digits, the (.a-z) refers to lowercase characters, the *A-Z refers to the uppercase characters and the {8,10} constrains the range to 8 – 10 characters.
For more information about regular expressions, see "How To: Use Regular Expressions to Constrain Input in ASP.NET 2.0."
Note that the SQL Server and Active Directory providers always first evaluate the password against the minRequiredPasswordLength and minRequiredNonalphanumericCharacters attributes. If the regular expression is intended to be the authoritative match, then you should set the other two attributes to weaker values, for example a minimum length of 1 and 0 non-alphanumeric characters.
The following configuration uses the minRequiredPasswordLength and minRequiredNonalphanumericCharacters attributes to constrain the password.

		 <membership defaultProvider="MySqlMembershipProvider">
		  <providers>
		    <add name="MySqlMembershipProvider" 
		         connectionStringName="MyLocalSQLServer" 
		         applicationName="MyAppName"
		         minRequiredPasswordLength="8"
		         minRequiredNonalphanumericCharacters="2"
		         type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
		  </providers>
		 </membership>
	

Validating Strong Passwords

You can also use a regular expression with the CreateUserWizard control to enforce passwords complexity rules. By doing so, you benefit from client-side validation in addition to server-side validation.
To validate a password entered through the CreateUserWizard control, set its PasswordRegularExpression property to an appropriate regular expression such as the one shown here:

		 ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
	

Additional Resources

* "How To: Protect Forms Authentication Tickets"
* "How To: Use Forms Authentication to Active Directory in ASP.NET 2.0"



Return to ASPNET2SecurityHowTos
Microsoft Communities