ASP.NET 2.0 Security Practices - Authentication

From Guidance Share

Jump to: navigation, search

Contents

How to choose between Windows authentication and forms authentication

Use Windows authentication when you can because it provides secure credential management, password policies, and user account management tools.

To choose between Windows authentication and forms authentication:

  • If your user accounts are in Active Directory or are local accounts, use Windows authentication if you can.
  • If you cannot use Windows authentication to your Active Directory store, use forms authentication to Active Directory, and use the ActiveDirectoryMembershipProvider.
  • If your user accounts are in a SQL Server database, use forms authentication to SQL Server, by using the SqlMembershipProvider.
  • If your user accounts are in ADAM, use forms authentication to ADAM, by using the ActiveDirectoryMembershipProvider.
  • If your user accounts are in a store other than the previously listed stores, create a custom membership provider and configure forms authentication to use it.


How to use Windows authentication in ASP.NET

To use Windows authentication in ASP.NET, you must use Microsoft Internet Information Services (IIS) to disable anonymous access and configure a Windows-based authentication method for your Web application's virtual directory. You are generally recommended to use Windows integrated authentication, but you can also use Basic, Digest, or client certificate authentication. You must also ensure that the mode attribute on the <authentication> element is set to "Windows" (the default setting) in your Web.config file.


For more information, see How To: Use Windows Authentication in ASP.NET 2.0.


How to use Kerberos authentication in ASP.NET

To use Kerberos authentication to authenticate the end users of your Web application, all computers must be in a Windows Server 2000 or later domain. Your clients must be using Internet Explorer version 5.5 or later. Your application's virtual directory must be configured for Integrated Windows authentication and anonymous access must be disabled. You must set <authentication mode="Windows" /> in your Web.config file.


If you run your application using a domain service account, you must register a service principal name (SPN) for that account in Active Directory to associate the account with the HTTP service on the Web server. To register an SPN, use the Setspn.exe utility as follows:

setspn -A HTTP/webservername domain\customAccountName

setspn -A HTTP/webservername.fullyqualifieddomainname domain\customAccountName


Note that you cannot have multiple Web applications with the same host name if you want them to have multiple identities and to use Kerberos authentication. This is an HTTP limitation, not a Kerberos limitation. The workaround is to have multiple Domain Name System (DNS) names for the same host, and start the URLs for each Web application with a different DNS name. For example, you would use http://app1 and http://app2 instead of http://site/app1 and http://site/app2.


Note: By default, Integrated Windows authentication is not enabled in Internet Explorer 6.


If your clients run Internet Explorer 6, you must enable the browser to respond to a negotiate challenge and perform Kerberos authentication. To do this, select the Enable Integrated Windows Authentication check box in the Security section of the Advanced tab of the Internet Options menu, and then restart the browser. Administrators can enable Integrated Windows authentication by setting the EnableNegotiate DWORD value to 1 in the following registry key: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings


How to use forms authentication in ASP.NET

In the machine-level Web.config file or your application's Web.config file, set the mode attribute on the <authentication> element to "Forms". In IIS, ensure that your Web site is configured for anonymous access. Deny unauthenticated users access to your Web site by configuring URL authorization. To do this, create an <authorization> element in Web.config with <deny users="?"/>.


ASP.NET 2.0 introduces the membership feature. This feature simplifies forms authentication and reduces the amount of code you need to write. For more information, see:


How to protect forms authentication

Use Secure Sockets Layer (SSL) to protect the forms authentication credentials and the forms authentication cookie passed from browser to server. Ensure that the authentication cookie is passed only over HTTPS connections. Encrypt and integrity check the authentication cookie, do not persist it on the client computer, and do not use it for personalization purposes; use a separate cookie for personalization. By default, the httpOnly cookie attribute is always set to true by forms authentication to protect cookie information from being accessed by client script. A secure <forms> element configuration is shown here.

<forms loginUrl="Secure\Login.aspx"
       protection="All"
       requireSSL="true"
       timeout="00:30:00" 
       slidingExpiration="true"
       name="YourAppName"
       path="/Secure" />


For new site designs, consider creating a separate subfolder for those pages that require authenticated and SSL-based access. If you cannot use SSL, consider reducing the cookie lifetime by reducing the timeout value to minimize the time window within which an attacker can use a captured authentication cookie to access your site. If you are in a scenario where you are concerned about cookie hijacking, consider reducing the timeout and setting slidingExpiration="false". If sliding expiration is turned off, the authentication cookie expires after the time out period irrespective of whether or not the user is active. After the timeout period, the user must re-authenticate.


Also ensure that your credential management is secure. Enforce strong passwords and protect your authentication login form against SQL injection attacks by validating and constraining input credentials, and by using parameterized stored procedures while accessing the user store. Secure the connection string that points to your user store for example by encrypting the connectionStrings section in your Web.config file. Do not store plaintext or encrypted passwords in your user store. Store non-reversible password hashes instead. For more information, see How To: Protect Forms Authentication in ASP.NET 2.0.


How to use membership in ASP.NET 2.0

To configure membership, you need to define a connection string to point to the provider store and configure your provider definition in the Web.config file.

To configure membership:

  1. Configure your application for forms authentication by setting <authentication mode="Forms"/>
  2. Add a connection string to the <connectionStrings/> section to point to your user store. If you are using the ActiveDirectoryMembershipProvider, this is a Lightweight Directory Access Protocol (LDAP) query string pointing to your user container in Active Directory or ADAM. If you are using the SqlMembershipProvider, this is a database connection string that points to your user store database.
  3. Add a <membership> section to configure your chosen membership provider.
  4. Configure the specific provider by creating a <providers> section beneath the <membership> element in your application's Web.config. The membership system supports a number of different providers:
    1. If your user accounts are in Active Directory or ADAM, use the ActiveDirectoryMembershipProvider.
    2. If your user accounts are in SQL Server, use SqlMembershipProvider.
    3. If your user accounts are in a store other than those previously listed, create a custom membership provider by inheriting from the MembershipProvider base class.
  5. Set the defaultProvider attribute on the <membership> element to your chosen provider.

To validate and manage users, use the Membership API (for example, Membership.CreateUser and Membership.ValidateUser) or use the Login controls, which automatically use your membership configuration.


For more information, see How to Use Membership in ASP.NET 2.0.


How to use forms authentication with SQL Server

To use forms authentication against a SQL Server user store, you use the SqlMembershipProvider.

To use this provider:

  1. Create the membership SQL Server database by using the Aspnet_regsql tool.
  2. Create a SQL Server login for your ASP.NET application's process identity (or impersonated identity if your application uses impersonation) and grant it the appropriate permissions in the membership database.
  3. Establish a connection string in Web.config that points to the membership database.
  4. Configure the <membership> element in Web.config for SqlMembershipProvider, specifying at least the connection string name and an application name. The membership system subdivides the membership database by application name.
  5. Set the defaultProvider attribute on <membership> element to the configured provider name.
  6. Configure password complexity rules if you need to override the defaults, which ensure a minimum length of 7 characters with one of them being non-alphanumeric.

A typical SQLMembershipProvider configuration is shown here.

<connectionStrings>
  <add name="MySqlConnection" connectionString="Server=MySqlServer;  
       Database=aspnetdb; Trusted_Connection=yes;" />
</connectionStrings>
<system.web>
    ...
  <membership defaultProvider="SqlProvider" userIsOnlineTimeWindow="15">
    <providers>
      <clear />
      <add 
        name="SqlProvider" 
        type="System.Web.Security.SqlMembershipProvider" 
        connectionStringName="MySqlConnection"
        applicationName="MyApplication"
        enablePasswordRetrieval="false"
        enablePasswordReset="true"
        requiresQuestionAndAnswer="true"
        requiresUniqueEmail="true"
        passwordFormat="Hashed" />
    </providers>
  </membership>


For more information, see How To: Use Forms Authentication with SQL Server in ASP.NET 2.0.


How to use forms authentication with Active Directory

To use forms authentication with Active Directory, you use the ActiveDirectoryMembershipProvider.

To use this provider:

  1. Configure a connection string in Web.config that contains an LDAP query string that points to your user's container in Active Directory.
  2. Configure the <membership> element in your Web.config file for ActiveDirectoryMembershipProvider specifying at least the connection string name and optionally the credentials of an account capable of accessing Active Directory with the necessary permissions. If you do not specify account credentials, your application's process identity is used to access Active Directory, regardless of whether your application uses impersonation. Either the account specified in the Web.config file or your process account must have the appropriate permissions to access Active Directory.
  3. Set the defaultProvider attribute on <membership> element to the configured provider name.

A typical ActiveDirectoryMembershipProvider configuration is shown here.

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

<system.web>
 ...
 <membership defaultProvider="MembershipADProvider">
  <providers>
    <add
      name="MembershipADProvider"
      type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
                connectionStringName="ADConnectionString"
                connectionUsername="<domainName>\administrator" 
                connectionPassword="password"/>
   </providers>
 </membership>
 ...
</system.web>


For more information, see How To: Use Forms Authentication with Active Directory in ASP.NET 2.0.


How to use forms authentication with Active Directory in multiple domains

  • Create a custom login page by using text boxes and buttons. You cannot use the ASP.NET version 2.0 login controls in a multiple domain scenario.
  • Configure your application for forms authentication in the Web.config file.
    <authentication mode="Forms">
      <forms
          name=".ADAuthCookie"       
          timeout="10" />
    </authentication>
    
  • Deny unauthenticated access to your Web application.
    <authorization> 
      <deny users="?" />
      <allow users="*" />
    </authorization>
    
  • Add a connection string to point to the relevant users container in the domain controller for each domain.
    <connectionStrings>
      <add name="TestDomain1ConnectionString" connectionString="LDAP://testdomain1.test.com/CN=Users,DC=testdomain1,DC=test,DC=com" />
      <add name="TestDomain2ConnectionString" connectionString="LDAP://testdomain2.test.com/CN=Users,DC=testdomain2,DC=test,DC=com" />
    ...
     </connectionStrings>
    
  • Configure the membership element and the ActiveDirectoryMembership providers in the Web.config file to point to each domain.
    <membership >
      <providers>
        <add
          name="TestDomain1ADMembershipProvider"
          type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0, 
                Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
          connectionStringName="TestDomain1ConnectionString"            
          connectionUsername="testdomain1\administrator" 
          connectionPassword="password"/>
        <add
          name="TestDomain2ADMembershipProvider"
          type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0, 
                Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
          connectionStringName="TestDomain2ConnectionString"    
          connectionUsername="testdomain2\administrator" 
          connectionPassword="password"/>
      </providers>
    ...
    </membership>
    

    Note that the preceding example assumes you are working in a test domain and specific credentials are specified to connect to your Active Directory. If you do include credentials, you should encrypt them by using the Aspnet_regiis.exe utility. If you do not specify credentials, your application's process identity is used to connect to Active Directory.

  • Authenticate users against the appropriate domain controller. You can obtain the domain controller name from the domain component of the supplied user name. The following example assumes that the user supplies a UPN of the form username@domainname.com.
    string[] partsOfUserName = 
      UserNameTextBox.Text.Split("@".ToCharArray());
    string domainName = partsOfUserName[1];
    MembershipProvider domainProvider;
    switch (domainName)
    {
      case "TestDomain1.test.com":
        domainProvider = Membership.Providers["TestDomain1ADMembershipProvider"];
      break;
      case "TestDomain2.test.com":
        domainProvider = Membership.Providers["TestDomain2ADMembershipProvider"];
        break;
      default:
        throw(new Exception("This domain is not supported"));
    }
    if (domainProvider.ValidateUser(UserNameTextBox.Text, 
                                    PasswordTextBox.Text))
    {
      if (Request.QueryString["ReturnUrl"] != null)
      {
       FormsAuthentication.RedirectFromLoginPage(UserNameTextBox.Text, 
                                                 false);
      }
      else
      {
        FormsAuthentication.SetAuthCookie(UserNameTextBox.Text, false);
      }
    }
    else
    {
      Response.Write("Invalid UserID and Password");
    }
    

For more information, see How To: Use Forms Authentication with Active Directory in Multiple Domains in ASP.NET 2.0.


How to enforce strong passwords using membership

You can strengthen user password requirements by configuring the attributes minRequiredPasswordLength, minRequiredNonAlphanumericCharacters, and passwordStrengthRegularExpression on your membership provider configuration.


If you are using the SqlMembershipProvider, the default password strength is set to a minimum password length of 7 characters with at least one non-alphanumeric character.


If you are using the ActiveDirectoryMembershipProvider with Active Directory, your domain password policy is used by default, although you can further strengthen password policy by overriding this with your membership configuration by using the attributes listed earlier. Similarly, if you are using ActiveDirectoryMembershipProvider with ADAM, your local password policy is used, although you can override this with your membership configuration.


For more information, see How To: Protect Forms Authentication in ASP.NET 2.0.


How to configure account lockout using membership

If you are using the SqlMembershipProvider, you use the maxInvalidPasswordAttempts and passwordAttemptWindows attributes. By default, these values are 5 and 10, respectively. This means you get 5 invalid attempts within 10 minutes before you are locked out.


If you are using the ActiveDirectoryMembershipProvider, your domain or local security policy controls the password lockout. Note that if an account is locked out by the provider, it is not locked out within Active Directory, so you could still log on to Windows with the account. However, the ActiveDirectoryMembershipProvider treats the account as locked out, so the user cannot logon through an application that uses the provider until the lockout duration elapses. Accounts locked out by the provider are re-enabled after a time interval defined by the attributeMapFailedPasswordAnswerLockoutTime attribute. Alternatively, you can write code that calls the UnlockUser method on the MembershipUser object.


How to enable password reset using ActiveDirectoryMembershipProvider

The ActiveDirectoryMembershipProvider class supports password reset security by requiring the user to answer a question that was provided along with an answer when the account was initially created.

To enable password reset:

  1. Extend your Active Directory schema to add new attributes to the built-in User class. To extend the User class:
    1. Add two single-valued attributes of type string to hold the password question and password answer.
    2. Add three new attributes to store tracking data used to manage account lockout, a single-valued attribute of type integer to track the failed answer count, a single-valued attribute of type Large integer/interval to hold the last time at which an invalid answer was supplied by the user while attempting to reset their password, and a single-valued attribute of type Large integer/interval to hold the time at which the account was locked out because of a succession of bad password answers being provided.
  2. Configure your <membership> element in Web.config for the ActiveDirectoryMembershipProvider. Set enablePasswordReset and requiresQuestionAndAnswer to true. Also set the series of mapping attributes to establish mappings to the extended Active Directory User object attributes that you created. Mapping attributes include attributeMapUsername, attributeMapPasswordQuestion, attributeMapPasswordAnswer, attributeMapFailedPasswordAnswerCount, attributeMapFailedPasswordAnswerTime, and atributeMapFailedPasswordAnswerLockoutTime.

    Your provider configuration to support password resets should look similar to the one here.
    <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" />
    
  3. Set the PasswordRecoveryText and PasswordRecoveryURL on your Login control. Set the URL to a page that contains a PasswordRecovery control. If a user has forgotten a password, he or she can click the password recovery text link on the Login control and then enter a user name. The PasswordRecovery control then prompts the user with the predetermined question. On submission of the correct answer, the ActiveDirectoryMembershipProvider resets the user's password to a randomly created password value of an appropriate strength, and then it sends an e-mail message to the user with the new password. The e-mail address is usually supplied during registration.
Personal tools