Every .NET developer has been there. You scaffold a new project, check the “Individual Accounts” box, and Microsoft drops a mountain of Identity scaffolding into your codebase — 47 files of Razor Pages, a dozen service registrations, and an Entity Framework schema that ships 8 tables you’ll never use. Meanwhile, the auth middleware you actually need requires a different NuGet package with a different token format and a different set of breaking changes every major release.

This is the .NET authentication identity crisis — and it’s not about security. It’s about identity, the library.

The Promise. ASP.NET Core Identity was supposed to be the one-stop shop: user management, password hashing, external logins, two-factor auth, and a pluggable store. Add Microsoft.Identity.Web for Azure AD integration, and you’re enterprise-ready. Sprinkle IdentityServer on top for OAuth2/OIDC token issuance, and you’re a standards-compliant identity provider. The architecture diagrams look clean. The brownfield reality does not.

The Fragmentation Tax. As of 2026, a typical enterprise .NET application that authenticates users, issues tokens, and integrates with Azure AD pulls in no fewer than five identity-related packages. Each has its own opinion about claim types. Each ships its own UserManager or equivalent. Each has its own middleware ordering requirements that, when violated, produce 500 errors with stack traces 14 frames deep before you hit your own code.

The problem compounds with dual-targeted libraries. A NuGet package targeting netstandard2.0 and net48 alongside net8.0 inherits an entirely different authentication surface. Microsoft.AspNetCore.Identity doesn’t exist on net48. System.Web.Security doesn’t exist on net8.0. Library authors resort to #if spaghetti that compiles but creates runtime behavior gaps nobody discovers until production.

The Real Cost. The cost isn’t in NuGet downloads or GitHub stars. It’s in the onboarding slowdown, the production incidents that trace back to mismatched token validation parameters, and the architecture meetings where teams debate whether to rip out Identity entirely and roll their own — only to rediscover why 8 tables exist in the first place.

I’ve watched senior engineers spend two days debugging an auth failure that turned out to be a claim type mismatch between Microsoft.Identity.Web (which emits http://schemas.microsoft.com/identity/claims/objectidentifier) and IdentityServer (which normalizes to the short oid claim). The application worked in development with hot reload. It failed in staging behind an ingress controller that stripped custom headers. The fix was three lines of ClaimActions.MapJsonKey. Finding those three lines took 14 hours.

IdentityServer’s Gravity. Much of the ecosystem’s auth complexity orbits IdentityServer. For years it was the de facto OAuth2/OIDC provider for .NET — free, open-source, deeply integrated with ASP.NET Core’s auth middleware. Then Duende Software changed the license. The community forked. Multiple forks emerged, each incompatible with the others’ configuration extensions. Today, AddIdentityServer() might resolve to three different assemblies depending on your NuGet restore graph.

Microsoft.Identity.Web then entered the picture as the blessed Azure AD path, but it targets a fundamentally different use case. It assumes a managed identity provider. It assumes cloud. It doesn’t help the 40% of .NET workloads still running on-premises Windows servers where Windows Authentication is the only identity system IT operations will approve.

The Path Forward. There’s no silver bullet, but there are pragmatic choices. First, minimize the auth surface area. If you don’t need token issuance, don’t pull IdentityServer or its forks. Microsoft.Identity.Web plus the base identity framework handles 80% of enterprise scenarios if Azure AD is your identity provider. Second, standardize claim transformations in a single middleware component — not scattered across controllers, policies, and JWT handlers. Third, test authentication as infrastructure, not as application logic. A broken auth pipeline shouldn’t require application logs to diagnose.

For library authors: target net8.0+ only if you’re building for the modern ecosystem. The netstandard2.0/net48 dual-targeting drag isn’t worth the maintenance cost for authentication-sensitive code. Document which authentication primitives your library expects and what happens when they’re absent.

Bottom Line. The .NET ecosystem’s authentication libraries are individually well-designed and collectively incoherent. Every new Microsoft.Identity release reshuffles the namespace. Every IdentityServer fork introduces slightly different configuration syntax. The result is an integration surface that looks simple in blog posts and behaves unpredictably in production. Until the platform ships a coherent, versioned authentication abstraction that spans self-hosted and cloud-hosted identity, every .NET solution architect should budget for auth integration as a first-class engineering concern — not a checkbox on the project template screen.