Authorization
|
This section documents ASP.NET Core on .NET 10 (LTS), the current release — the minimal hosting model, the middleware pipeline, dependency injection, Minimal APIs, MVC & Razor Pages, Blazor with the current render modes, SignalR and gRPC, EF Core, ASP.NET Core Identity and policy-based authorization, output caching, rate limiting, and Native-AOT-aware building — as described by the official documentation at Microsoft Learn, which is the reference these pages are written and verified against. This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. .NET ships a major release every November and its APIs continue to evolve: the examples here target .NET 10 / C# 14. This section’s bibliography lists the reference material consulted while preparing these pages. |
Authorization runs after authentication has identified the user. It ranges from a bare "must be signed in" to fine-grained, per-object rules.
UseAuthentication must come before UseAuthorization in the pipeline, and both after UseRouting, so the
selected endpoint’s authorization metadata is available.
[Authorize] and [AllowAnonymous]
[Authorize] // any authenticated user
public sealed class AccountController : ControllerBase
{
[AllowAnonymous] // opt one action back out
[HttpGet("public")] public IActionResult Public() => Ok();
}
// minimal endpoints and groups
app.MapGet("/me", GetProfile).RequireAuthorization();
app.MapGroup("/admin").RequireAuthorization("AdminOnly");
[Authorize] also works on Razor Pages, Blazor @page components, and SignalR hubs. See
Introduction to
authorization.
Simple, role, and claims checks
[Authorize(Roles = "Admin,Support")] // user is in either role
[Authorize(Policy = "EmailConfirmed")] // a named policy (defined below)
builder.Services.AddAuthorizationBuilder()
.AddPolicy("EmailConfirmed", p => p.RequireClaim("email_verified", "true"))
.AddPolicy("Over18", p => p.RequireAssertion(ctx =>
ctx.User.HasClaim(c => c.Type == "age") &&
int.Parse(ctx.User.FindFirstValue("age")!) >= 18));
Role checks are a special case of claims checks (ClaimTypes.Role). See
Role-based authorization.
Policy-based authorization
A policy is one or more requirements; each requirement has one or more handlers. This keeps rules out of controllers and makes them testable.
public sealed class MinimumTenureRequirement(int years) : IAuthorizationRequirement
{
public int Years { get; } = years;
}
public sealed class MinimumTenureHandler : AuthorizationHandler<MinimumTenureRequirement>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context, MinimumTenureRequirement requirement)
{
var hiredClaim = context.User.FindFirst("hired_on")?.Value;
if (DateOnly.TryParse(hiredClaim, out var hired) &&
hired.AddYears(requirement.Years) <= DateOnly.FromDateTime(DateTime.UtcNow))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
builder.Services.AddSingleton<IAuthorizationHandler, MinimumTenureHandler>();
builder.Services.AddAuthorizationBuilder()
.AddPolicy("Veteran", p => p.AddRequirements(new MinimumTenureRequirement(5)));
Multiple handlers for one requirement are OR’d (any Succeed passes); multiple requirements in a policy are
AND’d. See
Policy-based authorization.
Resource-based authorization
When the decision depends on the specific object (e.g. "only the author may edit this document"), evaluate the
policy imperatively with IAuthorizationService:
public sealed class DocumentController(IAuthorizationService auth) : ControllerBase
{
[HttpPut("{id:int}")]
public async Task<IActionResult> Update(int id, DocInput input)
{
var doc = await _repo.FindAsync(id);
if (doc is null) return NotFound();
var result = await auth.AuthorizeAsync(User, doc, "CanEditDocument");
if (!result.Succeeded) return Forbid();
// ...
return NoContent();
}
}
The matching handler derives from AuthorizationHandler<TRequirement, Document>. See
Resource-based
authorization.
Advanced policy features
-
IAuthorizationRequirementData— a single attribute that both declares and parameterises a requirement, e.g.[MinimumAge(18)]. -
Default policy — what a bare
[Authorize]means (default: authenticated user). -
Fallback policy — applied to every endpoint that has no other authorization metadata; set it to
RequireAuthenticatedUser()to make the whole app secure-by-default.builder.Services.AddAuthorizationBuilder() .SetFallbackPolicy(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build()); -
Multiple schemes —
[Authorize(AuthenticationSchemes = "Bearer,Cookies")]accepts either. -
View-level checks — inject
IAuthorizationServiceinto a Razor view, or use<AuthorizeView>in Blazor, to show/hide UI.