ASP.NET Core Authentication
When to Use This Skill
Use this skill when:
- Configuring OIDC authentication in an ASP.NET Core web application
- Setting up JWT Bearer authentication for an API
- Managing authentication schemes (cookies, OIDC, JWT, external providers)
- Implementing challenge, sign-in, sign-out, and forbid flows
- Debugging authentication failures (401s, redirect loops, claim mapping issues)
- Integrating with Duende IdentityServer as an OpenID Connect provider
- Configuring token validation parameters
Core Principles
- Authentication ≠ Authorization — Authentication establishes who the user is. Authorization (see
aspnetcore-authorization) determines what they can do. - Scheme-Based Architecture — ASP.NET Core authentication is built around named schemes. Each scheme has a handler that knows how to authenticate, challenge, and sign out.
- Cookies for Web Apps, JWT for APIs — Web applications use cookie authentication (with OIDC for login). APIs use JWT Bearer or introspection.
- Never Roll Your Own — Use the built-in OIDC and JWT Bearer handlers. They handle nonce validation, key rotation, token validation, and dozens of edge cases.
- Claim Type Mapping Matters — The OIDC handler maps JWT claim types to .NET claim types by default. Disable this for predictable claim names.
Related Skills
aspnetcore-authorization— Policy-based authorization after authenticationidentityserver-configuration— Server-side client and resource configurationidentityserver-sessions-providers— Server-side sessions to reduce cookie size and maintain IdP-side dataoauth-oidc-protocols— Protocol fundamentals underlying these handlerstoken-management— Automatic token refresh with Duende.AccessTokenManagement
Docs: https://docs.duendesoftware.com/identityserver/apis/aspnetcore/jwt/
Pattern 1: OIDC Authentication for Web Applications
The most common pattern — a server-rendered web app authenticating users via Duende IdentityServer:
Critical Settings Explained
Pattern 2: JWT Bearer Authentication for APIs
APIs validate access tokens issued by IdentityServer:
Multiple Audiences
When an API accepts tokens from multiple resources:
Pattern 3: Reference Token Introspection
For APIs that validate reference tokens (opaque tokens) instead of JWTs:
Install the
Duende.AspNetCore.Authentication.JwtBearerpackage which supports both JWT and reference token validation, switching automatically based on the token format.
Combined JWT + Reference Token Support
Pattern 4: Understanding Authentication Schemes
ASP.NET Core uses named authentication schemes. Each scheme is handled by a specific handler.
Default Schemes
The Authentication Flow
Pattern 5: Claim Type Mapping
By default, the Microsoft OIDC handler remaps JWT claims to XML-based .NET claim types. This causes confusion:
The Mapping Problem
The Fix — Always Disable Mapping
Why this matters: Without this,
User.FindFirst("sub")returnsnullbecause the claim was renamed. You'd need to use the verbose XML URI instead.
Pattern 6: OIDC Handler Events
The OIDC handler exposes events for customizing the authentication pipeline:
Common Event Use Cases
Pattern 7: Sign-Out
Proper sign-out must clear both the local cookie and the IdentityServer session:
The Sign-Out Flow
Important: Calling only
SignOutAsync("Cookies")withoutSignOutAsync("oidc")leaves the IdentityServer session active. The user will be silently re-authenticated on the next challenge.
Pattern 8: Accessing Stored Tokens
When SaveTokens = true, the access token, refresh token, and ID token are stored in the authentication cookie:
Better approach: Use
Duende.AccessTokenManagement(seetoken-managementskill) which handles token refresh, caching, and rotation automatically instead of manually managing stored tokens.
Pattern 9: mTLS (Certificate-Bound Tokens) with the OIDC Handler
When IdentityServer issues certificate-bound tokens via mTLS (RFC 8705), the OIDC client must (1) present its client certificate on all back-channel calls and (2) target the mTLS endpoint aliases. The stock handler does neither on its own.
Step 1 — Present the client certificate on back-channel calls
Set BackchannelHttpHandler so code redemption, refresh, and userinfo calls run over a mutually-authenticated TLS channel. No client secret is needed — the certificate authenticates the client:
Step 2 — Point the handler at mtls_endpoint_aliases
The stock OIDC handler reads endpoints from standard discovery metadata and does not understand mtls_endpoint_aliases — it would call the non-mTLS token_endpoint. Wrap the standard configuration manager and rewrite the endpoints to their mTLS aliases:
PAR + mTLS on .NET 9+: because the handler automatically uses PAR when the server advertises a
pushed_authorization_request_endpoint, you must rewrite that endpoint to the mTLS alias as well. Otherwise the pushed authorization request goes to the non-mTLS endpoint and the certificate binding is lost.
Common Pitfalls
1. Forgetting MapInboundClaims
2. Missing UseAuthentication Before UseAuthorization
3. Not Clearing Scopes Before Adding
4. Cookie Too Large (>4KB)
When SaveTokens = true and many claims are included, the cookie can exceed browser limits:
5. Redirect Loop After Login
Usually caused by the cookie not being set due to SameSite restrictions:


