wallybh
wallybh

Reputation: 952

Change password validation rules after application starts

Can I update my application validation rules after startup?

I tried something like this, but I got stuck in how I'll persist that Information.

public void UpdatePasswordValidation(SystemConfig config)
{
    var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();

    manager.PasswordValidator = new CustomPasswordValidator
            {
                DigitLength = config.PswNumber ?? 0,
                EspecialCharLength = config.PswEspecialChar ?? 0,
                LowercaseLength = config.PswLower ?? 0,
                RequiredLength = config.PswMinLength ?? 0,
                UppercaseLength = config.PswUpper ?? 0,
            };

    //How do I persist these rules in owin context?
}

Thanks in advance. Sorry for my poor english :(.

Upvotes: 0

Views: 872

Answers (1)

Michael Crook
Michael Crook

Reputation: 1535

If I understand what you are trying to do, you are attempting to:

  • modify the password validator
  • allow for rules to change during run time

then you can achieve this by utilizing both a custom password validator and with your web.config to store the values. The only issue I see with web.config is I think that upon changes it will restart your MVC site. If this was an issue, you could create an admin page which allowed the user to modify these values and then save the values to a db.

To create a custom validator you could impliment the IIdentityValidator interface and then inside of your UserManager class inside the constructor swap out the default PasswordValidator for your custom one. Like so:

public class CustomPasswordValidator : IIdentityValidator<string>
{
    public int RequiredLength { get; set; }

    public CustomPasswordValidator(int? length)
    {
        int webConfigMinimumPasswordLength;

        if (int.TryParse(WebConfigurationManager.AppSettings["MinimumPasswordLength"],
            out webConfigMinimumPasswordLength))
        {
            Console.WriteLine("Parsing config failed");
            webConfigMinimumPasswordLength = 6; // just go back to default
        }

        RequiredLength = length ?? webConfigMinimumPasswordLength;
    }

    public Task<IdentityResult> ValidateAsync(string item)
    {
        if (String.IsNullOrEmpty(item) || item.Length < RequiredLength)
        {
            return Task.FromResult(IdentityResult.Failed(String.Format("Password should be of length {0}",RequiredLength)));
        }

        string pattern = @"^(?=.*[0-9])(?=.*[!@#$%^&*])[0-9a-zA-Z!@#$%^&*0-9]{10,}$";

        if (!Regex.IsMatch(item, pattern))
        {
            return Task.FromResult(IdentityResult.Failed("Password should have one numeral and one special character"));
        }

        return Task.FromResult(IdentityResult.Success);
    }
}

then go into your UserManager deceleration (usually inside IdentityConfig.cs)

public class ApplicationUserManager : UserManager<ApplicationUser[PR6] >
{
    public ApplicationUserManager() : base(new UserStore<ApplicationUser(new ApplicationDbContext()))
    {
        // add the line below to your UserManager
        PasswordValidator = new CustomPasswordValidator();
    }
}

Hope this helps, if there are any more issues feel free to comment, I was unable to get this into an actual MVC project and ensure what I slapped together actually worked!

For more reading on Custom Password Validators, have a look at: http://blogs.msdn.com/b/webdev/archive/2014/01/06/implementing-custom-password-policy-using-asp-net-identity.aspx

Upvotes: 2

Related Questions