Validating User Passwords in SharePoint 2010

I recently wrote a user self-registration solution for SharePoint 2010. As part of this solution, I needed to validate the requested password to ensure that it met the requirements of the authentication provider (in this case, Active Directory).

The code, while hardly rocket science, is something I do not want to figure out again. So I thought I would post it here for my own benefit. If anyone else finds it useful, that’s cool, too!

I wanted to validate that the password met various requirements from the AD policy:

  1. 1. Length
  2. 2. Complexity (contains a combination of lower case, upper case, digits, and special characters.
  3. 3. Content (does not contain all or part of user name)

I did not need to check against old-passwords to prevent repetition, since this solution is creating new users.

Checking for length is blatantly obvious, so I won’t bother showing that.

For complexity, the default AD policy is as follows:

“Passwords must contain characters from three of the following four categories:

  1. English uppercase characters (A through Z).
  2. English lowercase characters (a through z).
  3. Base 10 digits (0 through 9).
  4. Non-alphabetic characters (for example, !, $, #, %).”

This is pretty simple to do. In fact there are several ways to do it, depending on whether you want to use regular expressions, built-in methods of the string class, etc.

  1. For digits and special symbols, I simply created character arrays for those two groups, and used the string class’ IndexOfAny method.
  2. I could have done the upper and lower case the same way, but I decided to take a different approach (just for variety). For a string S, if S==S.ToLowerCase(), then S contains no uppercase letters. Similarly for uppercase.
  3. Having determined the presence of the 4 classes of characters, I can then simply add up the number of character classes found.

So, code I have used for these conditions is:

The next interesting part was the content check. To check that no more than 2 consecutive letters of the user name or full name are used in the password, I iterate over the username, taking three-character substrings, and checking to see if the password contains them. This is then repeated for the full name. If any of the substrings is found, then the password fails:

   1: protected bool PasswordComplexityValidation(string UserName, string FullName, string Password)

   2: {

   3:     char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

   4:     char[] symbols = { '~', '!', '@', '#', '$', '%', '^', '&', '*', '_', '-', '+', '=', '`', '|', '\\', '(', ')', '{', '}', '[', ']', ':', ';', '"', '<', '>', ',', '.', '?', '/' };

   5:  

   6:     bool blnHasDigits = (Password.IndexOfAny(digits) != -1);

   7:     bool blnHasSymbols = (Password.IndexOfAny(symbols) != -1);

   8:     bool blnHasUpperCase = !(Password.Equals(Password.ToLower()));

   9:     bool blnHasLowerCase = !(Password.Equals(Password.ToUpper()));

  10:  

  11:     int conditionsMet = 0;

  12:  

  13:     if (blnHasDigits)

  14:         conditionsMet++;

  15:  

  16:     if (blnHasSymbols)

  17:         conditionsMet++;

  18:  

  19:     if (blnHasUpperCase)

  20:         conditionsMet++;

  21:  

  22:     if (blnHasLowerCase)

  23:         conditionsMet++;

  24:  

  25:     return (conditionsMet > 2);

  26: }

That is about it. I make no representations that this is the best way of validating passwords, or even the best. This is just what I thought up over the weekend!

   1: protected bool PasswordContentValidation(string UserName, string FullName, string Password)

   2: {

   3:     // Check that password does not contain a large part of the UserName or Full Name

   4:  

   5:     bool blnIsValid = true;

   6:  

   7:     // Check if password contains a 3 character substring from the username

   8:     for (int i = 0; i < (UserName.Length - 3); i++)

   9:     {

  10:         string substring = UserName.Substring(i, 3);

  11:         if (Password.Contains(substring))

  12:         {

  13:             blnIsValid = false;

  14:             break;

  15:         }

  16:     }

  17:  

  18:     // Do the same for 3-character substrings from the Full Name, but only if the password is not already invalid

  19:     if (blnIsValid)

  20:     {

  21:         for (int i = 0; i < (FullName.Length - 3); i++)

  22:         {

  23:             string substring = FullName.Substring(i, 3);

  24:             if (Password.Contains(substring))

  25:             {

  26:                 blnIsValid = false;

  27:                 break;

  28:             }

  29:         }

  30:     }

  31:     return blnIsValid;

  32: }