// Copyright (c) Microsoft Open Technologies, Inc. // All Rights Reserved // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING // WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF // TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR // NON-INFRINGEMENT. // See the Apache 2 License for the specific language governing // permissions and limitations under the License. using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity { /// /// Used to validate some basic password policy like length and number of non alphanumerics /// public class PasswordValidator : IPasswordValidator { /// /// Minimum required length /// public int RequiredLength { get; set; } /// /// Require a non letter or digit character /// public bool RequireNonLetterOrDigit { get; set; } /// /// Require a lower case letter ('a' - 'z') /// public bool RequireLowercase { get; set; } /// /// Require an upper case letter ('A' - 'Z') /// public bool RequireUppercase { get; set; } /// /// Require a digit ('0' - '9') /// public bool RequireDigit { get; set; } /// /// Ensures that the string is of the required length and meets the configured requirements /// /// /// /// public virtual Task ValidateAsync(string item, CancellationToken cancellationToken = default(CancellationToken)) { if (item == null) { throw new ArgumentNullException("item"); } var errors = new List(); if (string.IsNullOrWhiteSpace(item) || item.Length < RequiredLength) { errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.PasswordTooShort, RequiredLength)); } if (RequireNonLetterOrDigit && item.All(IsLetterOrDigit)) { errors.Add(Resources.PasswordRequireNonLetterOrDigit); } if (RequireDigit && !item.Any(IsDigit)) { errors.Add(Resources.PasswordRequireDigit); } if (RequireLowercase && !item.Any(IsLower)) { errors.Add(Resources.PasswordRequireLower); } if (RequireUppercase && !item.Any(IsUpper)) { errors.Add(Resources.PasswordRequireUpper); } return Task.FromResult(errors.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(String.Join(" ", errors))); } /// /// Returns true if the character is a digit between '0' and '9' /// /// /// public virtual bool IsDigit(char c) { return c >= '0' && c <= '9'; } /// /// Returns true if the character is between 'a' and 'z' /// /// /// public virtual bool IsLower(char c) { return c >= 'a' && c <= 'z'; } /// /// Returns true if the character is between 'A' and 'Z' /// /// /// public virtual bool IsUpper(char c) { return c >= 'A' && c <= 'Z'; } /// /// Returns true if the character is upper, lower, or a digit /// /// /// public virtual bool IsLetterOrDigit(char c) { return IsUpper(c) || IsLower(c) || IsDigit(c); } } }