Round #214

07 May 2026, 14:20· csharp· meta/llama-3.3-70b-instruct· r12-real-contracts
Complexity
band 1
ZP / UO / OBS
3 / 5 / 3
Journey weight
794
Lightshift ΔL

Prompt

Implement resource-based authorization using IAuthorizationHandler

Zero-point index (what the engine surfaced)

ZPI-ZPI-0007 | 2026-05-07T14:20:48Z Implement resource-based authorization using IAuthorizationHandler ZERO POINT — 3 entries (structural invariants) ● hsl(178.91, 100%, 21%) IAuthorizationHandler [contract] ● hsl(14.32, 100%, 21%) IAuthorizationRequirement [contract] ● hsl(349.17, 100%, 21%) AuthorizationHandler<TRequirement> [contract] UNOBSERVED — 5 entries (implied truths) ○ hsl(27.69, 100%, 50%) async [feature] ○ hsl(49.23, 100%, 30%) try [feature] ○ hsl(31.38, 100%, 40%) Scoped registration [function] ○ hsl(44.31, 100%, 25%) IOptions of T binding [function] ○ hsl(112.62, 100%, 16%) Token validation parameters [function] OBSERVED — 3 entries (explicit in request) ◉ hsl(85.13, 100%, 36%) using [feature] ◉ hsl(234.87, 100%, 36%) using [feature] ◉ hsl(121.85, 100%, 10%) Resource-based authorization [function] COMPLEXITY │ 11 entries │ spread: 207° │ band: MEDIUM

Baseline response (no ZPI)

**Resource-Based Authorization using IAuthorizationHandler** =========================================================== In this example, we will implement resource-based authorization using `IAuthorizationHandler` in a C# application. **Step 1: Create a Resource** --------------------------- First, let's create a resource that we want to protect with authorization. For example, let's create a `Document` class: ```csharp public class Document { public int Id { get; set; } public string Name { get; set; } public string OwnerId { get; set; } } ``` **Step 2: Create an Authorization Requirement** ------------------------------------------ Next, let's create an authorization requirement that will be used to protect the `Document` resource. We will create a `DocumentOwnerRequirement` class that inherits from `IAuthorizationRequirement`: ```csharp public class DocumentOwnerRequirement : IAuthorizationRequirement { public string DocumentId { get; set; } } ``` **Step 3: Create an Authorization Handler** ----------------------------------------- Now, let's create an authorization handler that will handle the `DocumentOwnerRequirement`. We will create a `DocumentOwnerHandler` class that inherits from `IAuthorizationHandler`: ```csharp public class DocumentOwnerHandler : AuthorizationHandler<DocumentOwnerRequirement> { private readonly IUserService _userService; private readonly IDocumentService _documentService; public DocumentOwnerHandler(IUserService userService, IDocumentService documentService) { _userService = userService; _documentService = documentService; } protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, DocumentOwnerRequirement requirement) { var userId = context.User.FindFirstValue(ClaimTypes.NameIdentifier); var document = await _documentService.GetDocumentAsync(requirement.DocumentId); if (document != null && document.OwnerId == userId) { context.Succeed(requirement); } } } ``` In this example, the `DocumentOwnerHandler` checks if the current user is the owner of the document. If the user is the owner, the handler succeeds the requirement. **Step 4: Register the Authorization Handler** -------------------------------------------- Finally, let's register the `DocumentOwnerHandler` in the `Startup.cs` file: ```csharp public void ConfigureServices(IServiceCollection services) { services.AddAuthorization(options => { options.AddPolicy("DocumentOwnerPolicy", policy => policy.Requirements.Add(new DocumentOwnerRequirement())); }); services.AddSingleton<IAuthorizationHandler, DocumentOwnerHandler>(); } ``` **Step 5: Use the Authorization Policy** ----------------------------------------- Now, we can use the `DocumentOwnerPolicy` to protect the `Document` resource. For example, we can create a controller that requires the `DocumentOwnerPolicy`: ```csharp [Authorize(Policy = "DocumentOwnerPolicy")] public class DocumentController : Controller { private readonly IDocumentService _documentService; public DocumentController(IDocumentService documentService) { _documentService = documentService; } [HttpGet] public async Task<IActionResult> GetDocument(int id) { var requirement = new DocumentOwnerRequirement { DocumentId = id.ToString() }; var result = await AuthorizationService.AuthorizeAsync(User, requirement); if (!result.Succeeded) { return Forbid(); } var document = await _documentService.GetDocumentAsync(id); return Ok(document); } } ``` In this example, the `DocumentController` requires the `DocumentOwnerPolicy` to access the `GetDocument` action. The `DocumentOwnerHandler` will check if the current user is the owner of the document, and if not, the action will return a 403 Forbidden response. **Example Use Case** -------------------- Here's an example use case: 1. Create a new document with an owner ID of "1". 2. Create a new user with an ID of "1" and a role of "Owner". 3. Log in as the user with ID "1". 4. Try to access the document with ID "1" using the `GetDocument` action. 5. The `DocumentOwnerHandler` will check if the current user is the owner of the document, and since they are, the action will return the document. Note: This is a simplified example and you should adapt it to your specific use case. Additionally, you should ensure that the `IUserService` and `IDocumentService` interfaces are properly implemented and registered in the DI container.

Enhanced response (with ZPI)

### Resource-Based Authorization Implementation Below is an example implementation of resource-based authorization using `IAuthorizationHandler`. This example includes a custom requirement, a custom handler, and registration in the DI container. #### Custom Requirement First, we define a custom requirement that will be used to specify the resource type and the operation being performed. ```csharp public class ResourceOperationRequirement : IAuthorizationRequirement { public string ResourceType { get; } public string Operation { get; } public ResourceOperationRequirement(string resourceType, string operation) { ResourceType = resourceType; Operation = operation; } } ``` #### Custom Handler Next, we create a custom handler that will evaluate the custom requirement. This handler will check if the user has permission to perform the specified operation on the specified resource type. ```csharp public class ResourceOperationHandler : AuthorizationHandler<ResourceOperationRequirement> { private readonly IOptions<AuthorizationSettings> _authorizationSettings; public ResourceOperationHandler(IOptions<AuthorizationSettings> authorizationSettings) { _authorizationSettings = authorizationSettings; } protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ResourceOperationRequirement requirement) { var claims = context.User.Claims; var userId = claims.FirstOrDefault(c => c.Type == "id")?.Value; // Check if the user has permission to perform the operation on the resource type if (HasPermission(userId, requirement.ResourceType, requirement.Operation)) { context.Succeed(requirement); } await Task.CompletedTask; } private bool HasPermission(string userId, string resourceType, string operation) { // This is a placeholder for your actual permission checking logic // You can use a database or a cache to store the permissions var permissions = _authorizationSettings.Value.Permissions; return permissions.ContainsKey(userId) && permissions[userId].ContainsKey(resourceType) && permissions[userId][resourceType].Contains(operation); } } public class AuthorizationSettings { public Dictionary<string, Dictionary<string, List<string>>> Permissions { get; set; } } ``` #### Registration in DI Container Finally, we register the custom handler and the custom requirement in the DI container. ```csharp public void ConfigureServices(IServiceCollection services) { services.AddAuthorization(options => { options.AddPolicy("ResourceOperationPolicy", policy => policy.Requirements.Add(new ResourceOperationRequirement("ResourceType", "Operation"))); }); services.AddSingleton<IAuthorizationHandler, ResourceOperationHandler>(); services.Configure<AuthorizationSettings>(Configuration.GetSection("AuthorizationSettings")); } ``` #### Usage To use the custom handler, you can decorate your controllers or actions with the `[Authorize]` attribute and specify the policy name. ```csharp [Authorize(Policy = "ResourceOperationPolicy")] public class MyController : Controller { [HttpGet] public IActionResult Get() { return Ok(); } } ``` In this example, the `ResourceOperationHandler` will be triggered when the `Get` action is called, and it will check if the user has permission to perform the `Operation` on the `ResourceType`. If the user has permission, the action will be executed; otherwise, a 403 Forbidden response will be returned. ### Explanation This implementation provides a basic example of resource-based authorization using `IAuthorizationHandler`. The custom requirement `ResourceOperationRequirement` specifies the resource type and the operation being performed, and the custom handler `ResourceOperationHandler` evaluates this requirement by checking if the user has permission to perform the operation on the resource type. The `ResourceOperationHandler` uses the `IOptions` interface to inject the `AuthorizationSettings` instance, which contains the permissions configuration. The `HasPermission` method checks if the user has permission to perform the operation on the resource type by looking up the permissions in the `AuthorizationSettings` instance. The custom handler is registered in the DI container as a singleton, and the custom requirement is added to the authorization policy. The `[Authorize]` attribute is used to decorate the controllers or actions that require authorization, and the policy name is specified to trigger the custom handler. This implementation provides a flexible and extensible way to implement resource-based authorization, and it can be customized to fit the specific requirements of your application.

Grader chain

Each grader reads the same baseline + enhanced pair and casts an independent verdict. Disagreement is the framework's own signal — not noise to be averaged away.

V1claude-haiku-4-5-20251001
Worse
V4qwen2.5-coder-7b-instruct
Better

Comments

Our grader said what it said. What do you say? Comment as a guest below.

No comments yet. Be the first to say what you make of this round.

← back to all rounds