Creating Custom Password Validation Rules In ASP.NET MVC, Using ASP.NET Identity

Microsoft ASP.NET MVC comes with a built-in Authentication Template which you can use in your project. When you create a new ASP.NET MVC project in Visual Studio, you can click on Change Authentication button and select Individual User Accounts to include the default Identity Template in your project,
 
Creating Custom Password Validation Rules In ASP.NET MVC, Using ASP.NET Identity 
 
When you open the project, you will notice the the following Authorization Template files have been added to your project,
 
Creating Custom Password Validation Rules In ASP.NET MVC, Using ASP.NET Identity
 
Open IdentityConfig.cs file, which contains the default implementation of password validation rules,
  1. public class ApplicationUserManager : UserManager<ApplicationUser>  
  2. {  
  3.     // some code ommited from here...  
  4.       
  5.     manager.PasswordValidator = new PasswordValidator  
  6.     {  
  7.         RequiredLength = 6,  
  8.         RequireNonLetterOrDigit = true,  
  9.         RequireDigit = true,  
  10.         RequireLowercase = true,  
  11.         RequireUppercase = true,  
  12.     };  
  13.               
  14.     // some more code....  
  15.     }  
  16. }  
Note: IdentityConfig.cs does not follow the most basic coding guideline, which is one class per file. I recommend moving the classes in this file to their respective files.
 
As you can see it is pretty straightforward to modify password strength rules, you can switch RequireDigit On/Off… you can change RequiredLength, etc.
 
But switching these rules wouldn’t produce a good password rule. Forcing users to include all Uppercase, Lowercase, Digits and SpecialSymbols can be very frustrating for users who already have a secure password which satisfies some of the above rules, but not all. As an example, Shopless uses the following password rule:
 
Password length should be a minimum of 8 characters and it should contain characters from at least 2 of the following groups: lower case, upper case, digits and special symbols. 
 
In order to implement the above rule, we need to create our own CustomPasswordValidator.cs,
 
As you can see, it is pretty straightforward to modify password strength rules, you can set RequireDigit as True/False and  change the min length, etc…
 
But switching these rules won’t produce a good password rule. Forcing users to include all Uppercase, Lowercase, Digits and SpecialSymbols can be very frustrating for users who already have a secure password which satisfies some of the above rules, but not all. A much better password rule would be:
  1. public class CustomPasswordValidator : IIdentityValidator<string>  
  2. {  
  3.     public int MinLength { get; set; }  
  4.     public CustomPasswordValidator(int minLength)  
  5.     {  
  6.         MinLength = minLength;  
  7.     }  
  8.   
  9.     // validate password: count how many types of characters exists in the password  
  10.     public Task<IdentityResult> ValidateAsync(string password)   
  11.     {  
  12.         if (String.IsNullOrEmpty(password) || password.Length < MinLength) {  
  13.             return Task.FromResult(IdentityResult.Failed("Password too short"));  
  14.         }  
  15.   
  16.         int counter = 0;  
  17.         List<string> patterns = new List<string>();  
  18.         patterns.Add(@"[a-z]"); // lowercase  
  19.         patterns.Add(@"[A-Z]"); // uppercase  
  20.         patterns.Add(@"[0-9]"); // digits  
  21.         patterns.Add(@"[!@#$%^&*\(\)_\+\-\={}<>,\.\|""'~`:;\\?\/\[\] ]"); // special symbols
  22.   
  23.         // count type of different chars in password  
  24.         foreach (string p in patterns) {  
  25.             if (Regex.IsMatch(password, p)) {  
  26.                 counter++;  
  27.             }  
  28.         }  
  29.   
  30.         if (counter < 2) {  
  31.             return Task.FromResult(IdentityResult.Failed("Use characters from min 2 of these groups: lowercase, uppercase, digits, special symbols"));  
  32.         }  
  33.         return Task.FromResult(IdentityResult.Success);  
  34.     }  
  35. }  
Note
Don't forget to include white space in special symbols.
 
The above code is self explanatory, we are using regular expression to count the types of characters included in the password string. We fail the validation if password is too short or it does not contain at least 2 different character types.
 
And now we can use our own CustomPawwordValidator,
  1. public class ApplicationUserManager : UserManager<ApplicationUser>  
  2. {  
  3.     // some code ommited from here...  
  4.       
  5.     manager.PasswordValidator = new CustomPasswordValidator(8 /*min length*/);  
  6.       
  7.     /* We don't need this any more 
  8.      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  9.      * manager.PasswordValidator = new PasswordValidator 
  10.      * { 
  11.      *    RequiredLength = 6, 
  12.      *    RequireNonLetterOrDigit = true, 
  13.      *    RequireDigit = true, 
  14.      *    RequireLowercase = true, 
  15.      *    RequireUppercase = true, 
  16.      * }; 
  17.      */  
  18.               
  19.     // some more code....  
  20.     }  
  21. }