Skip to content

Pragmatic.Authorization

The authorization engine for Pragmatic.Design: permissions, roles, groups, wildcard matching, resource (instance-level) policies, and a permission cache — declarative and observable.

Authorization in most .NET apps starts simple and rots. Permission strings are hardcoded and scattered across controllers; role-to-permission mapping lives in if-statements; wildcard handling is hand-rolled and inconsistent; instance-level checks (“can this user act on this invoice?”) are buried in business logic. Ask “what can the booking-manager role do?” and the answer means reading every controller.

// Typical: scattered, fragile, invisible
var permissions = User.Claims.Where(c => c.Type == "permission").Select(c => c.Value).ToHashSet();
if (!permissions.Contains("booking.reservation.cancel")
&& !permissions.Any(p => p == "booking.reservation.*")
&& !permissions.Contains("*"))
return Forbid();

Declare what is protected and how; the framework handles resolution, wildcard matching, caching, and enforcement.

[RequirePermission(BookingPermissions.Reservation.Cancel)]
[RequirePolicy<ReservationCancellationPolicy>]
public sealed partial class CancelReservationAction : VoidDomainAction
{
// business logic only — no authorization code here
}
// Roles compose from module definitions, declared once in Program.cs
app.UseAuthorization(authz =>
{
authz.MapRole<BookingManagerRole>(r => r
.IncludeDefinition<BookingOperator>()
.IncludeDefinition<CatalogReader>());
authz.AddResourceAuthorizer<InvoiceAuthorizer>(); // instance-level (ABAC)
authz.UsePermissionCache(TimeSpan.FromMinutes(5));
});
  • Permissions — wildcard-aware matching (booking.*, *), generated PermissionConstants from IPermission/IRole definitions.
  • Roles & groups — compose roles from reusable definitions; map groups to roles.
  • Resource policies (ResourcePolicy) — instance-level “can this user act on this object?” checks.
  • Stores & caching — pluggable role/permission/group stores; cross-request HybridCache.
  • Pipeline enforcement[RequirePermission] / [RequirePolicy] enforced in the Actions/Endpoints pipeline.
Terminal window
dotnet add package Pragmatic.Authorization
dotnet add package Pragmatic.SourceGenerator # generates permission constants/registry

Roles, groups, wildcard permissions, resource authorizers, and the permission cache are functional within the 0.8 preview. See the roadmap.

| Concepts | Mental model, permission strings, the resolution chain, where authorization runs | | Getting Started | Protect an action, define permissions, map a role | | Permission Resolution | The full resolution chain, wildcard matching, caching | | Roles & Groups | IRole/IRoleDefinition, composition, groups | | Policies | ResourcePolicy, [RequirePolicy<T>], instance-level (ABAC) checks | | Stores | Role/permission/group stores, customization, temporal/tenant variants | | Common Mistakes | The most frequent authorization pitfalls | | Troubleshooting | Problem/solution guide with diagnostics |

Enforced by Actions and Endpoints; identity comes from Identity; data-level filters live in Persistence. Interfaces live in Pragmatic.Abstractions.

  • .NET 10.0+
  • Pragmatic.SourceGenerator analyzer

Part of the Pragmatic.Design ecosystem — see Licensing. Pragmatic.Authorization is licensed under the PolyForm Small Business 1.0.0 license (free for small businesses; commercial license above the threshold).