Documentation Index
Fetch the complete documentation index at: https://docs.neuro-tech.io/llms.txt
Use this file to discover all available pages before exploring further.
Authorization
Protect routes with controller-level authorization middleware and method-level requirements
Two attributes, two jobs
Authorization is split into two parts:
[UseAuthorization] — turns on authorization middleware for a controller
[Authorization] — adds role or permission requirements to a specific method
Attribute-based authorization
[Controller]
[Route("/projects")]
[UseAuthorization(typeof(ProjectPermissionMiddleware))]
public sealed class ProjectsController : ControllerBase
{
[HttpGet("/[projectId]")]
[Authorization(Permission = "read:projects")]
public Task<ProjectResponse> Get(string ProjectId)
{
return Task.FromResult(new ProjectResponse { ProjectId = ProjectId });
}
}
public sealed class ProjectResponse
{
public string ProjectId { get; set; } = string.Empty;
}
public sealed class ProjectPermissionMiddleware : AuthorizationMiddleware<PermissionAuthorizationRequirement>
{
public override Task Authorize(AuthorizationContext Context, PermissionAuthorizationRequirement Requirement)
{
Context.Authorized = Context.HttpContext?.User is not null
&& Requirement.Permission == "read:projects";
return Task.CompletedTask;
}
}
How the flow works
[UseAuthorization] registers one or more controller-level authorization middleware types
[Authorization] adds requirements to individual methods
AuthorizationMiddleware<T> only receives requirements of type T
- The middleware must set
AuthorizationContext.Authorized = true
- Rejected requirements return
403 Forbidden
Roles and permissions together
[Controller]
[Route("/admin")]
[UseAuthorization(typeof(ProjectPermissionMiddleware))]
[UseAuthorization(typeof(AdminRoleMiddleware))]
public sealed class AdminController : ControllerBase
{
[HttpGet("/dashboard")]
[Authorization(Permission = "read:projects")]
[Authorization(Role = "Administrator")]
public Task<DashboardResponse> Get()
{
return Task.FromResult(new DashboardResponse { Message = "authorized" });
}
}
Low-level equivalent
Router.UseAuthorization("/projects");
Router.RegisterMiddleware("/projects", new ProjectPermissionMiddleware().Invoke);
Router.SetAuthorization(
HttpMethodType.Get,
"/projects/[projectId]",
new PermissionAuthorizationRequirement("read:projects"));
When to choose attributes vs manual setup
Choose attributes when:
- The route is already controller-based
- The requirement belongs naturally to one endpoint
- You want the policy close to the action method
Choose the manual API when:
- Registering low-level endpoints directly
- You need fine-grained control over pipeline wiring
- Building a reusable router module outside controller discovery
What to read next
Advanced Patterns covers raw request handling, manual endpoints, and parameter-name codecs.