Integrating ASP.NET Identity Password Policies with Password Managers

Scott Brady
Scott Brady
ASP.NET Identity

Modern HTML attributes such as “passwordrules” and “autocomplete” allow you to tell password generators where your set password fields are and how they should generate passwords.

While password complexity rules are not the best approach for security, ASP.NET Core Identity does use them by default. This includes requirements for uppercase and special characters.

In this article, you will learn how you can automatically implement the “perfect” set password field using your existing ASP.NET Identity password policy and a tag helper found in “ScottBrady.IdentityModel”.

ASP.NET Core Identity & password policies

ASP.NET Core Identity comes preconfigured to require uppercase, lowercase, digits, and non-alphanumeric characters. This policy can conflict with some password generators or the user’s particular password generation settings. If you are enforcing password rules server-side, then it is my opinion that they should be communicated client-side before the user submits an invalid password.

passwordrules in ASP.NET Core Identity

As part of my ScottBrady.IdentityModel helper library, I have created an ASP.NET Core tag helper for new passwords. This takes the password policy defined in your ASP.NET Identity PasswordOptions and automatically builds an input element with the correct passwordrules and attributes.

This means that you can write a newpassword element in your cshtml:

<newpassword asp-for="Password" />

And, when using the default ASP.NET Identity password policy, get the following input element in your html:

<input class="form-control" id="password" type="password" name="Password" value=""
autocomplete="new-password" autocorrect="off" autocapitalize="off" minlength="6"
passwordrules="minlength: 6; required: lower; required: upper; required: digit; required: special;" >

This element is configured with attributes based on your ASP.NET Core Identity PasswordOptions:

  • RequiredLength sets the minlength password rule and minlength attribute
  • RequireDigit: sets the required: digit passwordrule
  • RequireLowercase: sets the required: lower passwordrule
  • RequireUppercase: sets the required: upper passwordrule
  • RequireNonAlphanumeric: sets the required: special passwordrule

Try it yourself

See if your password generator is compatible with passwordrules by using this form input:

  • Minimum length: 25+ characters
  • Requires: digits, uppercase, lowercase, and special characters

If your password generator supports this, then you should see it suggest a password that meets these policies. If it doesn't, then you'll either get one that doesn't or see nothing at all.

Using the newpassword tag helper for registration

To use this tag helper in your registration or update page, you’ll need to install the helper library from NuGet. This package has a framework dependency on ASP.NET Core.

dotnet add package ScottBrady.IdentityModel.AspNetCore

You can now enable the tag helpers in your views by adding the following line to your _ViewImports.cshtml file.

@addTagHelper *, ScottBrady.IdentityModel.AspNetCore

You can now update the password fields on your registration or password update forms with the following, where "Password" is a property on your model. Much like other tag helpers, you can include other attributes in the element, such as class.

<newpassword asp-for="Password" />

This results in an input field configured with attributes such as “passwordrules”, “minlength”, and “autocomplete”, based on your ASP.NET Core Identity password options.

Optional: Maximum length and maximum consecutive characters rules

You can also add support for the maximum length and maximum consecutive character rules by changing your PasswordOptions to be of type ScottBrady.IdentityModel.AspNetCore.Identity.ExtendedPasswordOptions.

services.AddIdentityCore<IdentityUser>(options =>
{
    options.Password = new ExtendedPasswordOptions
    {
        RequiredLength = 15,
        RequireDigit = true,
        RequireLowercase = true,
        RequireUppercase = true,
        RequireNonAlphanumeric = true,
        
        // extended options
        MaxLength = 64,
        MaxConsecutiveChars = 3
    };
})

This can then be enforced server-side using the ExtendedPasswordValidator:

services.AddIdentityCore<IdentityUser>(/* options */)
  .AddPasswordValidator<ExtendedPasswordValidator<IdentityUser>>()

The “max-consecutive characters” uses a basic regex to validate consecutive characters. It is overridable if you need to cover edge-cases that this regex misses.

ScottBrady.IdentityModel.AspNetCore

Hopefully, using PasswordOptions as the single point of password complexity rule configuration will make life simpler for you when someone inevitably expresses an opinion about the rules and asks you to change them. For a full explanation of the “passwordrules” attribute, check out my other article, “Perfecting the password field with the HTML passwordrules attribute”.

For more helper libraries in “ScottBrady.IdentityModel”, check out its support for JWTs signed with EdDSA and .NET implementations of JWT alternatives such as Branca and PASETO.