Authentication

patterns & practices Developer Center

Authentication is one of the most important pillars of security. Where possible, you should use Windows authentication because this enables you to use an existing identity store such as your organization's Active Directory and to enforce strong password policies. You do not need to build custom identity store management tools, and passwords are not transmitted over the network.

This section provides guidance on choosing the correct authentication option for your scenario:

  • Know your authentication options.
  • Use Windows authentication when you can.
  • If your users are in Active Directory, but you can't use Windows authentication, consider using username authentication.
  • If you are using username authentication, use a membership provider instead of custom authentication.
  • If your users are in a SQL Server membership store, use the SQL Server membership provider.
  • If your users are in a custom store, consider using usernam authentication with a custom validator.
  • If your clients have certificates, consider using client certificate authentication.
  • If your partner applications need to be authenticated when calling WCF services, use client certificate authentication.
  • If you are using usernam authentication, validate user login information.
  • Do not store passwords directly in the user store.
  • Enforce strong passwords.
  • Protect access to your credential store.
  • If you are using client certificate authentication, limit the certificates in the certificate store.

Each of these guidelines is described in the following sections.

Know your authentication options

It is important to understand the authentication options that map to your deployment scenario.

Internet

  • Username authentication with the SQL Server membership provider. If your users are not in Active Directory, consider using the SQL Server membership provider. This will give you a store that can be easily created and deployed. Both message security and mixed-mode security support username authentication, and the authentication in WCF can be configured to use this authentication mode. Additionally, username authentication can cross firewall boundaries. Consider using transport security with a custom HTTP module that is redirected to authenticate with the SQL Server membership provider.
  • Basic authentication with Active Directory. If your users are already in Active Directory or in local machine accounts, consider using username password with Basic authentication. Transport security supports this authentication mode. The service can be hosted either in Windows service or in IIS.
  • Username authentication with a custom store. If your users are already in a custom store, or if you need to use a custom store because other platform applications might have access to it, consider using username authentication with a custom validator. Both message security and mixed-mode security support this authentication mode. Additionally, username authentication can cross firewall boundaries.
  • Certificate authentication with Windows. If your clients are partners, or mobile clients connecting over a virtual private network (VPN), consider using certificate authentication. This configures a peer-to-peer authentication scenario. Optionally, you can map the certificates to Windows accounts, for authorization checks based on Windows roles. Certificate authentication has the benefits of providing a secure infrastructure and the ability to cross firewall boundaries. All security modes, depending on the binding used, support this authentication mode. The tradeoff is that using this authentication mode requires you to manage certificates. Also, a public key infrastructure (PKI) can be expensive to maintain.

Intranet

  • Username authentication with the SQL Server membership provider. If your users are not in Active Directory, consider using the SQL Server membership provider. This will give you a store that can be easily created and deployed. Both message security and mixed-mode security support username authentication, and the authentication in WCF can be configured to use this authentication mode. Additionally, username authentication can cross firewall boundaries. Consider using transport security with a custom HTTP module that is redirected to authenticate with the SQL Server membership provider.
  • Windows authentication with Active Directory. If your users are already in Active Directory, consider using Windows authentication to leverage the deployment and investment in the infrastructure. This authentication mode also gives the benefits of using Windows roles for authorization checks. Both transport security and message security support Windows authentication. Windows authentication also supports message security without requiring you to install certificates.
  • Username authentication with a custom store. If your users are already in a custom store, or if you need to use a custom store because other platform applications might have access to it, consider using username authentication with a custom validator. Both message security and mixed-mode security support this authentication mode. Username authentication can also cross firewall boundaries.
  • Certificate authentication with Windows. Consider using certificate authentication when you cannot use Windows authentication because of a firewall between the client and the service. Certificate authentication has the benefits of providing a secure infrastructure and the ability to cross firewall boundaries. All security modes, depending on the binding used, support this authentication mode. Optionally, you can map the certificates to Windows accounts for authorization checks based on Windows roles. The tradeoff is that using certificate authentication requires you to manage certificates. Also, a PKI can be expensive to maintain.

Additional Resources

Use Windows authentication when you can

Use Windows authentication in the following scenarios:

  • When both the client and service are in trusted domains, such as in an intranet scenario. By using Windows authentication with Active Directory, you benefit from a unified identity store, centralized account administration, enforceable account and password policies, and strong authentication that avoids sending passwords over the network.
  • When the service uses a local machine account, the client can authenticate by using the NTLM protocol. However, because NTLM is not secured, this can expose the service to man-in-the-middle attacks, where the hash password sent over the network can be compromised by brute-force attacks. Although Windows authentication can be used without Active Directory, you should consider using more secure methods such as certificate authentication.

If your users are in Active Directory but you can't use Windows authentication, consider using usernam authentication

If your users are in Active Directory and you cannot use Windows authentication (e.g., in an Internet scenario), consider using username authentication. Your users will be mapped to a Windows account by default. By using username authentication with Windows accounts, you benefit from having a unified identity store, centralized account administration, and enforceable account and password policies.

If you are using usernam authentication, use a membership provider instead of custom authentication

If you are using username authentication in WCF and your users are not in Active Directory, use a membership provider, in this case the SQL Server membership provider. Do not try to implement your own user authentication mechanism.

The membership feature is a good choice because it allows you to enable username authentication without writing and maintaining custom code. The membership provider can be integrated into a WCF application in order to authenticate consumers of your service. Use a WCF binding such as wsHttpBinding that supports username/password credentials, and set the client credential type to UserName. Configure the membership provider in your configuration file to authenticate users against the membership store.

The following configuration snippet shows how to configure the username authentication with a membership provider:

  1. Set the membership provider configuration:

    <connectionStrings>
        <add name="MyLocalSQLServer"
             connectionString="Initial Catalog=aspnetdb;data source=10.3.19.60;Integrated Security=SSPI;"/>
      </connectionStrings>
    
      <system.web>
    
        <membership defaultProvider="MySqlMembershipProvider" >
          <providers>
            <clear/>
            <add name="MySqlMembershipProvider"
                 connectionStringName="MyLocalSQLServer"
                 applicationName="MyAppName"
                 type="System.Web.Security.SqlMembershipProvider" />
          </providers>
        </membership>
      </system.web>
    
  2. Set the client credentials to UserName:

    <wsHttpBinding>
     <binding name="BindingConfiguration">
      <security>
      <message clientCredentialType="UserName" />
       </security>
     </binding>
    </wsHttpBinding>
    
  3. Set the Service Credentials configuration to use the membership provider:

    …
    <serviceBehaviors>
      <behavior name="BehaviorConfiguration">
        …
        <serviceCredentials>
          <userNameAuthentication userNamePasswordValidationMode="MembershipProvider"
            membershipProviderName=" MySqlMembershipProvider " />
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
    …
    

If your users are in a SQL Server membership store, use the SQL Server membership provider

If your user information is already stored in the aspnetdb database, or if you are building an Internet-facing WCF application from scratch, use the SQL Server membership provider to authenticate your WCF service clients. The SQL Server membership provider authenticates all incoming client credentials against the credentials stored in the SQL Membership database. The membership feature is a good choice because it allows you to enable username authentication without writing and maintaining custom code. The SQL Server membership provider is configured in the Service config file. The following example illustrates a service's SQL Server membership provider configuration:

  1. Set the SQL membership provider configuration:

    …
    <connectionStrings>
        <add name="MyLocalSQLServer"
             connectionString="Initial Catalog=aspnetdb;data source=10.3.19.60;Integrated Security=SSPI;"/>
    </connectionStrings>
    <system.web>
    …
          <membership defaultProvider="MySqlMembershipProvider" >
            <providers>
              <clear/>
              <add name="MySqlMembershipProvider"
                   connectionStringName="MyLocalSQLServer"
                   applicationName="MyAppName"
                   type="System.Web.Security.SqlMembershipProvider" />
            </providers>
          </membership>
    …
    </system.web>
    …
    
  2. Set your binding to use username authentication as follows:

    …
    <bindings>
      <wsHttpBinding>
        <binding name="BindingConfiguration">
          <security>
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    …
    
  3. Set the service credentials configuration to use the SQL Server membership provider with username authentication:

    …
    <serviceBehaviors>
      <behavior name="BehaviorConfiguration">
        <serviceCredentials>
          <userNameAuthentication userNamePasswordValidationMode="MembershipProvider"
            membershipProviderName="MySqlMembershipProvider" />
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
    …
    

If your users are in a custom store, consider using usernam authentication with a custom validator

If you need to use a custom authentication store, consider using username authentication with a custom username and password validator. Configure the custom validator in a service behavior and implement it in a class library. The username and password validator is used by your service to authenticate your users based on your custom user store.

The following configuration snippet shows how to configure a custom validator for your WCF service:

<serviceCredentials>
   <userNameAuthentication  
    userNamePasswordValidationMode="Custom"
   customUserNamePasswordValidatorType="MyUserNamePasswordValidator,Host"/>
</serviceCredentials>

The following code snippet shows how to implement a custom username and password validator:

using System;
using System.Collections.Generic;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Text;

namespace DerivativesCalculator
{
    public class MyUserNamePasswordValidator : UserNamePasswordValidator
    {
        public override void Validate(string userName, string password)
        {
            Console.Write("\nValidating username, {0}, and password, {1} ... ", userName, password);
            if ((string.Compare(userName, "don", true) != 0) || 
                (string.Compare(password, "hall", false) != 0))
            {
               throw new SecurityTokenException("Unknown user.");
            }
            Console.Write("Done: Credentials accepted. \n");
        }
    }
}

If your clients have certificates, consider using client certificate authentication

Client certificates can authenticate a client service account or multiple users to a WCF service. If you use a client certificate for each user, you can map each certificate to a Windows account.

Enable the Windows account mapping feature by setting the mapClientCertificateToWindowsAccount attribute to true as follows:

<serviceCredentials>
    <clientCertificate>
        <authentication mapClientCertificateToWindowsAccount="true" />
    </clientCertificate>
</serviceCredentials>

If your partner applications need to be authenticated when calling WCF services, use client certificate authentication

If you have partners who need to consume your services, consider using transport security with client certificate authentication. This type of authentication allows clients to authenticate without prompting for a username and password.

In order to support client certificate authentication, you will need to add a <clientCertificate> reference to the client configuration file. The following client configuration example links the client certificate to the binding:

    <behaviors>
      <endpointBehaviors>
        <behavior name="ClientCertificateBehavior">
          <clientCredentials>
            <clientCertificate findValue="client.com"   
                               storeLocation="CurrentUser" 
                               storeName="My" 
                               x509FindType="FindBySubjectName" />
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>

If you are using usernam authentication, validate user login information

If you are using username authentication, validate the user-provided usernames and passwords for type, length, format, and range. Input and data validation represents one line of defense in the protection of your WCF application. Use regular expressions to constrain the input at the server.

If you are not using the SQL Server membership provider and need to develop your own queries to access your user store database, do not use login details to dynamically construct SQL statements because this makes your code susceptible to SQL injection. Instead, validate the input and then use parameterized stored procedures.

The following code snippet shows how to validate the credentials of a new user by using regular expressions.

using System;
using System.Text.RegularExpressions;

public void CheckNewUserCredentials(string name, string password)
{
    // Check name contains only lower case or upper case letters, 
    // the apostrophe, a dot, or white space. Also check it is 
    // between 1 and 40 characters long
    if ( !Regex.IsMatch(userIDTxt.Text, @"^[a-zA-Z'./s]{1,40}$"))
      throw new FormatException("Invalid name format");

    // Check password contains at least one digit, one lower case 
    // letter, one uppercase letter, and is between 8 and 10 
    // characters long
    if ( !Regex.IsMatch(passwordTxt.Text, 
                      @"^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$" ))
      throw new FormatException("Invalid password format");

    // Perform data access logic (using type safe parameters)
    ...
}

Do not store passwords directly in the user store

Do not store user passwords in plaintext or in encrypted format. Instead, store password hashes with a salt. By storing your password with hashes and salt, you help prevent an attacker that gains access to your user store from obtaining the user passwords. If you use encryption, you have the added problem of securing the encryption key. Use one of the membership providers to help protect credentials in storage and, where possible, specify a hashed password format on your provider configuration.

If you must implement your own user stores, store one-way password hashes with a salt. Generate the hash from a combination of the password and a random salt value. Use an algorithm such as SHA256. If your credential store is compromised, the salt value helps to slow an attacker who is attempting to perform a dictionary attack or rainbow table. This gives you additional time to detect and react to the compromise.

Enforce strong passwords

Ensure that your passwords are complex enough to protect against brute-force or dictionary attacks against your user credential store.

When using username authentication with the ASP.NET membership provider, users are forced to use strong passwords by default. For example, the SQL Server membership provider and the Active Directory membership provider ensure that passwords are at least seven characters in length, with at least one non-alphanumeric character. Ensure that your membership provider configuration enforces passwords of at least this strength.

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 here apply to the SQL Server membership provider and the Active Directory membership provider. The Active Directory membership provider also verifies passwords against the default domain password policy.

Protect access to your credential store

Ensure that only those accounts that require access are granted access to your credential store. This helps to protect the credential store by limiting access to it. For example, consider limiting access to only your application's account. Ensure that the connection string used to identify your credential store is encrypted.

Also consider storing your credential database on a server that is physically separate from your WCF application server. This makes it more difficult for an attacker to compromise your credential store even if he or she manages to take control of your server.

If you are using client certificate authentication, limit the certificates in the certificate store

If you are using certificate authentication, consider reducing the attack surface by limiting the certificates in the certificate store. Keep in mind the following considerations:

  • Consider deleting all the root certificates from the trusted root certification authorities store that are not required in order to authenticate your clients.
  • If your client base is large, consider using chain trust validation instead of peer trust so that you will have a smaller number of certificates to manage.
  • If your client base is small, consider using peer trust validation authentication. This will require that you manage one certificate per user. Any users not installed in the trusted people store will be denied access to the service.