Round #239
07 May 2026, 20:31· csharp· meta/llama-3.3-70b-instruct· r13-clean-hints
- Complexity
- band 1
- ZP / UO / OBS
- 3 / 5 / 3
- Journey weight
- 794
- Lightshift ΔL
- +0.00
Prompt
Implement resource-based authorization using IAuthorizationHandler
Zero-point index (what the engine surfaced)
ZPI-ZPI-0007 | 2026-05-07T20:31:35Z
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 the `IAuthorizationHandler` interface in C#. This approach allows you to authorize access to specific resources based on the user's permissions.
**Step 1: Create a Resource**
---------------------------
First, let's create a simple resource class that represents the resource we want to authorize access to:
```csharp
public class Document
{
public int Id { get; set; }
public string Name { get; set; }
public string OwnerId { get; set; }
}
```
**Step 2: Create a Policy Requirement**
--------------------------------------
Next, let's create a policy requirement that defines the authorization rule for the resource:
```csharp
public class DocumentOwnerRequirement : IAuthorizationRequirement
{
public string OwnerId { get; }
public DocumentOwnerRequirement(string ownerId)
{
OwnerId = ownerId;
}
}
```
**Step 3: Implement the Authorization Handler**
---------------------------------------------
Now, let's implement the `IAuthorizationHandler` interface to handle the authorization logic:
```csharp
public class DocumentOwnerHandler : AuthorizationHandler<DocumentOwnerRequirement>
{
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, DocumentOwnerRequirement requirement)
{
var userId = context.User.FindFirstValue(ClaimTypes.NameIdentifier);
if (userId == requirement.OwnerId)
{
context.Succeed(requirement);
}
}
}
```
In this implementation, we check if the user's ID matches the owner ID of the document. If they match, we succeed the authorization requirement.
**Step 4: Register the Authorization Handler**
---------------------------------------------
To use the authorization handler, we need to register it 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 Attribute**
------------------------------------------
Finally, let's use the `[Authorize]` attribute to protect a controller action that returns a document:
```csharp
[ApiController]
[Route("api/[controller]")]
public class DocumentsController : ControllerBase
{
[HttpGet("{id}")]
[Authorize(Policy = "DocumentOwnerPolicy")]
public IActionResult GetDocument(int id)
{
var document = new Document { Id = id, Name = "Example Document", OwnerId = User.FindFirstValue(ClaimTypes.NameIdentifier) };
return Ok(document);
}
}
```
In this example, the `GetDocument` action is protected by the `DocumentOwnerPolicy`. When a user requests the action, the `DocumentOwnerHandler` will check if the user is the owner of the document. If they are, the action will return the document. Otherwise, the action will return a 403 Forbidden response.
**Example Use Case**
--------------------
To test the authorization logic, you can create a test user with a specific ID and try to access a document that belongs to that user. If the user is the owner of the document, the action should return the document. If the user is not the owner, the action should return a 403 Forbidden response.
```csharp
[TestMethod]
public async Task GetDocument_Owner_ReturnsDocument()
{
// Arrange
var userId = "example-user-id";
var documentId = 1;
var document = new Document { Id = documentId, Name = "Example Document", OwnerId = userId };
// Act
var response = await _httpClient.GetAsync($"api/documents/{documentId}");
// Assert
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsAsync<Document>();
Assert.AreEqual(documentId, result.Id);
Assert.AreEqual(userId, result.OwnerId);
}
[TestMethod]
public async Task GetDocument_NonOwner_ReturnsForbidden()
{
// Arrange
var userId = "example-user-id";
var documentId = 1;
var document = new Document { Id = documentId, Name = "Example Document", OwnerId = "other-user-id" };
// Act
var response = await _httpClient.GetAsync($"api/documents/{documentId}");
// Assert
Assert.AreEqual(HttpStatusCode.Forbidden, response.StatusCode);
}
```
Note that this is a simplified example and you may need to adapt it to your specific use case. Additionally, you should always follow best practices for security and authorization in your application.
Enhanced response (with ZPI)
```csharp
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Threading.Tasks;
// Define a custom authorization requirement
public class ResourceAuthorizationRequirement : IAuthorizationRequirement
{
public string Resource { get; set; }
}
// Implement a custom authorization handler
public class ResourceAuthorizationHandler : AuthorizationHandler<ResourceAuthorizationRequirement>
{
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ResourceAuthorizationRequirement requirement)
{
// Get the current user's claims
var claims = context.User.Claims;
// Check if the user has access to the required resource
if (claims.Any(c => c.Type == "ResourceAccess" && c.Value == requirement.Resource))
{
context.Succeed(requirement);
}
await Task.CompletedTask;
}
}
// Register the authorization handler in the DI container
public static class AuthorizationExtensions
{
public static void AddResourceAuthorization(this IServiceCollection services)
{
services.AddSingleton<IAuthorizationHandler, ResourceAuthorizationHandler>();
}
}
// Example usage:
public class MyController : Controller
{
[Authorize(Policy = "ResourcePolicy")]
public IActionResult MyAction()
{
return View();
}
}
// Configure the authorization policy
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization(options =>
{
options.AddPolicy("ResourcePolicy", policy => policy.Requirements.Add(new ResourceAuthorizationRequirement { Resource = "MyResource" }));
});
services.AddResourceAuthorization();
}
```
This implementation provides a custom authorization handler that checks if the current user has access to a specific resource. The `ResourceAuthorizationRequirement` class defines the requirement, and the `ResourceAuthorizationHandler` class implements the logic to handle this requirement.
The `AddResourceAuthorization` method registers the authorization handler in the DI container. The example usage demonstrates how to apply the authorization policy to a controller action using the `[Authorize]` attribute.
In the `ConfigureServices` method, the authorization policy is configured to require the `ResourceAuthorizationRequirement` for the "ResourcePolicy" policy. The `AddResourceAuthorization` method is called to register the authorization handler.
This implementation uses the `IAuthorizationHandler` and `IAuthorizationRequirement` interfaces, as well as the `AuthorizationHandler<TRequirement>` class, to provide a custom authorization mechanism. The `Scoped` registration is not necessary in this case, as the authorization handler is registered as a singleton. The `IOptions<T>` binding is also not required, as the authorization handler does not rely on any configuration options. Token validation parameters are not applicable in this example, as the authorization handler relies on the user's claims to determine access to the resource.
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
WorseV4qwen2.5-coder-7b-instruct
BetterComments
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.