December 22, 2025

Meeting NIST 800-63B Password Requirements with ASP.NET Core Identity

Get compliant with NIST Identity guidelines to protect your end users and meet your client's demands

What This Guide Covers

If your security team or a compliance audit has flagged NIST 800-63B as something you need to target and you’re running ASP.NET Core Identity for authentication, this guide explains where the defaults fall short and exactly what to change. It applies to ASP.NET Core Identity on .NET 7 or later. For a developer familiar with your codebase, it should be a relatively light lift.

60-Second Background

NIST Special Publication 800-63B is the federal standard for digital authentication. Even if you’re not a government contractor, it’s increasingly referenced in enterprise security requirements, SOC 2 audits, and vendor assessments.

The standard covers three Authenticator Assurance Levels (AAL1, AAL2, AAL3).

AAL1 (single-factor): Content sites, forums, e-commerce without stored payment methods, internal tools. Password-only is acceptable.

AAL2 (multi-factor): SaaS platforms handling PII, healthcare apps, financial dashboards, enterprise software. Requires MFA.

AAL3 (hardware-based MFA): Banking cores, payment processors, government systems, critical infrastructure. Requires hardware tokens with phishing resistance. Most web applications target AAL1 (single-factor) or AAL2 (multi-factor). This guide focuses on the password (”memorized secret”) requirements that apply to both.

Also, the OWASP ASVS (Application Security Verification Standard) provides testable security requirements that complement NIST guidance. ASVS Chapter V6 (Authentication) maps closely to NIST 800-63B, but frames requirements as verification checkpoints your team can test against. If you’re building a security program or preparing for a pen test, cross-reference both.

  • NIST says 8 character minimum, OWASP recommends 15+
  • No complexity rules
  • Rate limit login attempts
  • Securely store passwords
  • Check and prevent common and breached passwords

Use Adversis’s interactive ASVS reference to filter requirements by level and chapter.

Talking Points for Security Reviews

When a customer’s security questionnaire, or an auditor asks, “Are you NIST 800-63B compliant?”, here’s how you can frame it after you’ve followed this guide.

“Our password policies align with NIST 800-63B requirements for memorized secrets and we target AAL1. We enforce minimum length without arbitrary complexity rules, per NIST guidance and check passwords against known breach databases before accepting them. We also implement rate limiting on authentication attempts. Sessions time out after 8 hours of inactivity.

They might be fine with security feature policy language or may want specific configuration screenshots or code snippets or documentation for.

ASP.NET Core Identity Defaults Miss the Mark

Out of the box, .NET 7+ Identity gets two things right. 1) password hashing (PBKDF2-HMAC-SHA512, 100k iterations) and 2) no artificial max length.

Non-compliant defaults

  • Minimum length is 6 characters (NIST requires 8)
  • No breach checking (NIST requires it)
  • Rate limiting defaults vary by template

Actively contradicts NIST

  • Identity requires uppercase, lowercase, digit, and symbol by default.
    • NIST explicitly prohibits these complexity rules since they produce predictable patterns like “P@ssw0rd1!” rather than strong passwords

If you’re on .NET 6 or earlier, hashing is also a problem since it defaults to only 10,000 iterations with SHA-256.

Cost of These Changes

Configuration changes (password policy, lockout settings) are straightforward and are low-risk.

Adding breach checking and common password validation requires some hours each to implement the validators.

Session timeout changes are quick but probably affect user experience and will take some conversation.

UI changes like paste support and visibility toggle are straightforward frontend work.

Existing user password migration needs a communication plan dev work depending on your approach.

Configuration Changes

Fix Password Policy Settings

In your Program.cs (or Startup.cs for older projects), update the Identity configuration:

builder.Services.Configure<IdentityOptions>(options =>
{
    // NIST 800-63B compliant password settings
    options.Password.RequiredLength = 8;           // NIST minimum
    options.Password.RequireDigit = false;         // NIST says don't require
    options.Password.RequireLowercase = false;     // NIST says don't require
    options.Password.RequireUppercase = false;     // NIST says don't require
    options.Password.RequireNonAlphanumeric = false; // NIST says don't require
    options.Password.RequiredUniqueChars = 1;      // Minimal uniqueness check
    
    // Rate limiting / lockout
    options.Lockout.MaxFailedAccessAttempts = 100; // NIST maximum before lockout
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
    options.Lockout.AllowedForNewUsers = true;
});

Add Breached Password Checking

NIST requires checking passwords against known compromised lists. ASP.NET Core Identity doesn’t include this, so you need a custom validator. The most practical approach uses the HaveIBeenPwned API (free, k-anonymity model protects user privacy). We’ll spare you the long code snippets, but effectively:

1. SHA-1 hash the password
2. Send first 5 characters to HIBP API (k-anonymity preserves privacy)
3. Check if remaining hash suffix appears in response
4. Return IdentityResult.Failed if found

Note:

  • The HaveIBeenPwned API is rate-limited. For high-volume registration, cache responses or use their downloadable hash files.
  • The catch block above fails open (allows registration if API is unavailable). Add monitoring to detect when this happens—you’ll want to know if breached passwords are slipping through.
  • Decide fail-open vs fail-closed when API is unavailable - fail open, but add monitoring
  • Consider logging (without the password) when rejections occur to track effectiveness.
  • Set a descriptive User-Agent header per HIBP’s terms

Block Common Passwords

Beyond breached passwords, NIST requires blocking dictionary words and predictable patterns. OWASP ASVS V6.1.4 specifies checking against at least the top 3,000 passwords. Implement a IPasswordValidator<TUser> that checks against a blocklist


1. Load top 3,000+ passwords into HashSet (from SecLists)
2. Check if password matches blocklist
3. Check for sequential patterns and repetition (abcdef, 123456, aaaaaa)
4. Return IdentityResult.Failed with specific message if blocked

Notes

  • Use SecLists or similar for production blocklist
  • Add context-specific terms: company name, product names, “SeasonYear”, etc.
  • This check and HIBP are complementary—a password can pass one and fail the other
  • OWASP ASVS V6.1.4 specifies 3,000 passwords; consider 10,000+

Session Timeout Configuration

NIST 800-63-4 specifies maximum session lengths.

  • AAL1 allows up to 30 days with optional inactivity timeout.
  • AAL2 requires 24-hour maximum session with 1-hour inactivity timeout.
  • AAL3 requires 12-hour maximum with 15-minute inactivity.

Configure via ConfigureApplicationCookie: set ExpireTimeSpan to your max session, and disable SlidingExpiration for AAL2+ to prevent indefinite extension.

ASP.NET’s sliding expiration extends on any request, including background API calls. True idle detection (user inactivity vs application activity) requires frontend tracking or custom middleware.

What You Can’t Configure Away

Some NIST requirements do need UI or architectural changes beyond Identity configuration:

Password visibility toggle - NIST recommends letting users see their password while typing. Add a show/hide button on password fields.

No password hints - NIST prohibits storing “hints” that unauthenticated users can access. If your app has a “forgot password hint” feature, remove it.

No security questions - “What was your first pet’s name?” violates NIST guidance. These are social engineering vulnerabilities.

Paste support - Users should be able to paste passwords (which enables password managers). Don’t disable paste on password fields.

User feedback on rejection - When rejecting a password, tell users why. Generic “password not strong enough” messages don’t help.

Testing Your Implementation

Before declaring compliance, verify these behaviors.

  1. Verify that 7-character passwords are rejected while 8-character lowercase-only passwords are accepted (no complexity requirement).
  2. Common passwords like “password123” should be rejected, as should repetitive (”aaaaaaaaaa”) and sequential (”abcdefghij”) patterns.
  3. Test HIBP integration with a known breached password like “P@ssw0rd”
  4. Confirm that 100 failed logins trigger lockout and that attempt 101 remains locked.

Handling Existing Users

New password policies only apply at password creation or change. Existing users with weak passwords won’t be forced to update. You have a few options here.

  1. Passive migration: Check passwords against new rules at login. If non-compliant, prompt for reset. Least disruptive and slow. Consider allowing grace period with this communication.
  2. Forced reset: Expire all passwords and require reset. Fast but high friction. Expect support tickets. Not recommended.

Communicate to users why you’re asking them to change passwords.

Scope Limitations

This guide covers memorized secrets (passwords) only. Full NIST 800-63B compliance involves additional areas:

  • Multi-factor authentication for AAL2/AAL3 - support passkeys!
  • Cryptographic authenticator requirements (hardware tokens, etc.)
  • Verifier security (TLS requirements, secure storage)
  • Session management beyond basic timeouts

If your compliance requirements specify AAL2 or AAL3, you’ll need MFA implementation beyond what’s covered here. OWASP ASVS Chapters V6.2 through V6.4 provide testable requirements for these additional controls.

References

Ready to make security your competitive advantage?

Schedule a call