SecurityProductionMVCAugust 2026 · 8 min read

ASP.NET Core Identity Best Practices: Secure Authentication Done Right

TL;DR

Production-grade ASP.NET Core Identity is configuration discipline as much as code: enforce a real password policy, lock accounts after failed attempts, enable 2FA and email confirmation, keep secrets out of source control, and assign the least privilege by default.

Most authentication breaches are not exotic zero-days — they are weak passwords, unencrypted secrets, missing lockout, and unconfirmed emails. ASP.NET Core Identity gives you the tools to prevent all of them, but only if you configure them. This article is the ASP.NET Core Identity best-practices checklist for production .NET 10 MVC applications, with the exact settings and code to apply.

Enforce a Real Password Policy

Length matters more than character classes. Set a minimum length of 10-12 characters and keep digit/uppercase requirements reasonable so users are not pushed toward predictable patterns:

builder.Services.AddIdentity<AppUser, IdentityRole>(options =>
{
    options.Password.RequiredLength = 10;
    options.Password.RequiredUniqueChars = 6;
    options.Password.RequireDigit = true;
    options.Password.RequireUppercase = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonAlphanumeric = false;
});

Lock Accounts After Failed Attempts

Brute-force protection is configuration, not code. Five failed attempts followed by a fifteen-minute lockout defeats most automated attacks:

options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
options.Lockout.AllowedForNewUsers = true;

Always call PasswordSignInAsync(..., lockoutOnFailure: true) so the policy actually applies, and surface result.IsLockedOut to the user with a dedicated view.

Require Email Confirmation and 2FA

Gate sign-in on a confirmed email and make two-factor authentication available for sensitive operations:

options.SignIn.RequireConfirmedEmail = true;
options.SignIn.RequireConfirmedAccount = true;

For the 2FA setup, generate the authenticator key and QR code with GetAuthenticatorKeyAsync and verify with TwoFactorAuthenticatorSignInAsync. Email confirmation also prevents sign-ups with fake addresses and reduces spam accounts.

Keep Secrets Out of Source Control

The IdentityDataProtection key and any token signing keys must never appear in appsettings.json. Use the Secret Manager during development and environment variables or a key vault in production:

// Development
dotnet user-secrets set "Jwt:Key" "dev-only-key"

// Production: environment variable or Key Vault reference
builder.Services.AddDataProtection()
    .PersistKeysToAzureBlobStorage(blobSasUri)
    .ProtectKeysWithAzureKeyVault(keyId, credential);

Apply Least Privilege and Audit Role Changes

  • Assign new users the Guest or Member role, never Admin by default
  • Use [Authorize(Roles = "Admin")] only where truly required
  • Log every role assignment and removal with user id and timestamp for auditability
  • Prefer claims-based policies over stacking roles for fine-grained rules

Do Not Roll Your Own Authentication

The most important best practice is also the simplest: use the framework. Custom password hashing, homegrown session tokens, and hand-written "remember me" logic are the source of most vulnerabilities. ASP.NET Core Identity already handles PBKDF2-style hashing, cookie protection, CSRF-aware sign-in, and token-based flows. Build on it. The MVC EDevKit Basic starter is a reference implementation of all of these practices in one codebase.

Key Takeaways

  • Require 10+ character passwords with uniqueness, not just character classes
  • Lock accounts after five failed attempts for fifteen minutes
  • Require confirmed email and offer two-factor authentication
  • Keep signing keys and Data Protection keys out of source control
  • Assign least privilege, audit role changes, and never reinvent Identity

FAQ

What password policy should I use? A minimum length of 10-12 characters with at least 6 unique characters. Modern guidance favors length over forced character classes.

Is account lockout enough to stop brute force? Lockout stops simple online brute force. For stronger protection, combine it with rate limiting, 2FA, and monitoring of failed logins.

Should I force 2FA for every user? At minimum make it available; many organizations require it for admin accounts. A pragmatic middle ground is enforced 2FA for privileged roles.

Where should production secrets live? Environment variables, Azure Key Vault, or a similar secret store — never in appsettings.json committed to git.

Study a production Identity configuration end to end?

MVC EDevKit Basic applies all of these Identity best practices — password policy, lockout, 2FA, email confirmation, JWT, and Firebase SSO — in one $21 codebase.

View MVC EDevKit Details