# How ASP.NET Core Handles Authentication and Authorization: A Deep Dive into the Security Middleware Pipeline

> Discover how ASP.NET Core expertly separates authentication and authorization using middleware in the request pipeline to secure your web applications effectively.

- Repository: [.NET Platform/aspnetcore](https://github.com/dotnet/aspnetcore)
- Tags: deep-dive
- Published: 2026-07-13

---

**ASP.NET Core separates authentication (identifying the user) from authorization (controlling access) into two distinct middleware components that run sequentially in the request pipeline, using dependency-injected services to validate credentials and enforce policies before reaching your application code.**

In the dotnet/aspnetcore repository, ASP.NET Core implements security as a layered middleware architecture where authentication and authorization operate as distinct but coordinated concerns. Understanding how ASP.NET Core handles authentication and authorization requires examining the internal implementations that intercept requests, validate security tokens, and enforce access policies based on endpoint metadata. The framework achieves this through two primary middleware classes that populate `HttpContext.User` and evaluate authorization policies against endpoint requirements.

## The Authentication Pipeline

The `AuthenticationMiddleware` class located in [`src/Security/Authentication/Core/src/AuthenticationMiddleware.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Security/Authentication/Core/src/AuthenticationMiddleware.cs) serves as the entry point for identity validation. This middleware creates the infrastructure for authenticating requests and establishes the security principal that downstream components consume.

### Creating the Authentication Feature

When a request enters the pipeline, the middleware immediately establishes tracking infrastructure by setting an `IAuthenticationFeature` on the HTTP context. According to the source code, this feature stores the original request path for later use during challenge or redirect operations. The middleware initializes this feature using `context.Features.Set<IAuthenticationFeature>(new AuthenticationFeature ...)`, ensuring that authentication handlers can access the original URL even if the request gets modified during processing.

### Handling Request Handlers

Before performing default authentication, the middleware iterates through registered `IAuthenticationRequestHandler` implementations using `await Schemes.GetRequestHandlerSchemesAsync()`. These specialized handlers, such as those for OpenID Connect or Ws-Federation, receive an opportunity to process the request directly. If a request handler handles the authentication challenge (for example, processing an OAuth callback), the pipeline short-circuits immediately, preventing unnecessary processing of the remaining middleware chain.

### Default Authentication and User Population

If no request handler processes the request, the middleware obtains the default authentication scheme via `IAuthenticationSchemeProvider` and executes `await context.AuthenticateAsync(defaultAuthenticate.Name)`. Upon successful authentication, the middleware populates `HttpContext.User` with the resulting principal using `context.User = result.Principal`. Additionally, it registers an `IHttpAuthenticationFeature` containing the authentication result, enabling downstream middleware like authorization to access the authenticated identity and authentication properties without re-validating credentials.

## The Authorization Pipeline

Following authentication, the `AuthorizationMiddleware` in [`src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs) determines whether the authenticated user possesses sufficient permissions to access the requested resource. This middleware operates on endpoint metadata and policy-based authorization requirements.

### Policy Resolution and Caching

The middleware first retrieves the endpoint using `context.GetEndpoint()` and inspects its metadata for `IAuthorizeData` attributes or custom policy configurations. It constructs the effective authorization policy by calling `AuthorizationPolicy.CombineAsync`, which merges requirements from the endpoint metadata with the default policy provider configuration. For performance optimization, the middleware optionally caches the computed policy using `_policyCache!.Store(endpoint!, policy)`, eliminating redundant policy construction for repeat requests to the same endpoint.

### Policy Evaluation and Enforcement

The middleware utilizes `IPolicyEvaluator` to perform two critical operations. First, it calls `await policyEvaluator.AuthenticateAsync(policy, context)` to re-run authentication respecting the policy's specific authentication schemes, updating the `IHttpAuthenticationFeature` with the latest results. Subsequently, it executes `await policyEvaluator.AuthorizeAsync(policy, ...)` to validate the principal against the policy's requirements. If authorization fails, the middleware invokes `IAuthorizationMiddlewareResultHandler` to generate appropriate `401` or `403` responses, or proceeds to the next middleware if the policy succeeds.

## Middleware Interaction Flow

The sequential registration of these middleware components creates a coordinated security boundary:

1. **`app.UseAuthentication()`** inserts `AuthenticationMiddleware` into the pipeline, which validates credentials and establishes `HttpContext.User`.
2. The authentication middleware runs request handlers and executes the default authentication scheme, storing results in HTTP features.
3. **`app.UseAuthorization()`** inserts `AuthorizationMiddleware`, which evaluates endpoint-specific policies against the authenticated principal.
4. The authorization middleware retrieves endpoint metadata, combines policies, and uses `IPolicyEvaluator` to authenticate and authorize the request.
5. If authorization fails, `IAuthorizationMiddlewareResultHandler` produces the challenge or forbidden response; otherwise, the request proceeds to application endpoints.

Both middlewares rely on dependency-injected services including `IAuthenticationSchemeProvider` for discovering configured schemes, `IAuthenticationHandlerProvider` for resolving specific handlers, `IPolicyEvaluator` for central authorization logic, and `IAuthorizationPolicyProvider` for supplying default and custom policies.

## Extensibility and Custom Implementations

The architecture supports extensive customization through handler interfaces. **Custom authentication handlers** implement `IAuthenticationHandler` or `IAuthenticationRequestHandler` and register via `services.AddAuthentication().AddScheme<...>()`. **Custom authorization policies** require implementing `IAuthorizationRequirement` and a corresponding `IAuthorizationHandler`, then attaching policies to endpoints using the `[Authorize]` attribute or explicit endpoint metadata configuration.

## Implementation Example

The following example demonstrates configuring both middleware components with cookie and JWT authentication, plus a custom authorization policy:

```csharp
var builder = WebApplication.CreateBuilder(args);

// Register authentication schemes
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddCookie()
.AddJwtBearer(options =>
{
    options.Authority = "https://login.example.com/";
    options.Audience = "api1";
});

// Register authorization policies
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AdminOnly", policy =>
        policy.RequireRole("Administrator"));
});

var app = builder.Build();

// Insert middleware in correct order
app.UseAuthentication();   // Runs AuthenticationMiddleware
app.UseAuthorization();    // Runs AuthorizationMiddleware

app.MapGet("/admin", [Authorize("AdminOnly")] (HttpContext ctx) =>
{
    return Results.Ok($"Hello {ctx.User.Identity?.Name}");
});

app.Run();

```

The `UseAuthentication` call wires the `AuthenticationMiddleware` that populates `HttpContext.User`, while `UseAuthorization` inserts the `AuthorizationMiddleware` that evaluates the `"AdminOnly"` policy against the endpoint metadata before executing the request delegate.

## Summary

- **AuthenticationMiddleware** in [`src/Security/Authentication/Core/src/AuthenticationMiddleware.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Security/Authentication/Core/src/AuthenticationMiddleware.cs) establishes identity by running request handlers and authenticating the default scheme, storing results in `HttpContext.User` and `IHttpAuthenticationFeature`.
- **AuthorizationMiddleware** in [`src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs) evaluates policies using `IPolicyEvaluator` to check the authenticated principal against endpoint requirements.
- **Middleware Ordering** matters: `UseAuthentication()` must precede `UseAuthorization()` to ensure the user principal exists before policy evaluation.
- **Policy Caching** improves performance by storing computed authorization policies per endpoint.
- **Extensibility** comes through `IAuthenticationHandler` for custom schemes and `IAuthorizationHandler` for custom authorization requirements.

## Frequently Asked Questions

### What is the difference between UseAuthentication and UseAuthorization in ASP.NET Core?

`UseAuthentication()` registers the `AuthenticationMiddleware` that validates security credentials and populates `HttpContext.User` with the authenticated principal. `UseAuthorization()` registers the `AuthorizationMiddleware` that evaluates authorization policies against that principal based on endpoint metadata. Authentication must run before authorization in the pipeline because authorization decisions depend on the identity established during authentication.

### How does the AuthorizationMiddleware determine which policy to apply?

The middleware retrieves the current endpoint using `context.GetEndpoint()` and inspects its metadata for `IAuthorizeData` implementations, such as the `[Authorize]` attribute. It calls `AuthorizationPolicy.CombineAsync` to merge requirements from the endpoint metadata with the default policy, optionally caching the result for subsequent requests. The computed policy specifies which authentication schemes to use and which requirements the user must satisfy.

### Can authentication handlers short-circuit the request pipeline?

Yes. The `AuthenticationMiddleware` iterates through registered `IAuthenticationRequestHandler` implementations before performing default authentication. If a handler processes the request (for example, handling an OAuth callback or WS-Federation sign-in), it can short-circuit the pipeline by completing the response, preventing subsequent middleware from executing. This behavior is defined in [`src/Security/Authentication/Core/src/AuthenticationMiddleware.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Security/Authentication/Core/src/AuthenticationMiddleware.cs).

### How do custom authentication schemes integrate with the pipeline?

Custom schemes implement `IAuthenticationHandler` or `IAuthenticationRequestHandler` and register through `services.AddAuthentication().AddScheme<TOptions, THandler>()`. The `AuthenticationMiddleware` resolves these handlers using `IAuthenticationSchemeProvider` and `IAuthenticationHandlerProvider`, allowing custom logic for credential validation and challenge generation to execute within the standard authentication flow.