#csharp #dotnet #backend

Day 24: Authorization (Role & Policy-Based)

Welcome to Day 24. Yesterday, we set up Authentication (verifying who you are). Today, we implement Authorization (verifying what you are allowed to do).

Just because Bob logging in successfully doesn’t mean Bob should be able to delete the entire production database.

Claims & Roles

Inside a JWT, you can store data about the user safely (as long as it’s not sensitive, like passwords). These pieces of data are called Claims.

A very common claim is the role.

  • Alice: role: Admin
  • Bob: role: User

When generating a token for Alice upon login in C#, you would inject the role claim into the JWT:

var claims = new[]
{
    new Claim(JwtRegisteredClaimNames.Sub, user.Id),
    new Claim(ClaimTypes.Role, "Admin")
};

Role-Based Authorization

When the token comes back to the server, ASP.NET Core magically parses its claims. You can restrict endpoints immediately based on Roles!

Controllers

[Authorize(Roles = "Admin")]
[HttpDelete("{id}")]
public IActionResult DeleteUser(int id) { ... }

Minimal APIs

app.MapDelete("/users/{id}", (int id) => { ... })
   .RequireAuthorization(new AuthorizeAttribute { Roles = "Admin" });

If Bob (who only has User) hits this endpoint, ASP.NET Core intercepts it and returns a 403 Forbidden. The method logic never executes!

Policy-Based Authorization

Roles are great, but they are rigid. What if you have a complex rule: “Users can delete posts, but only if they are the original author of the post OR if they are an Admin.”

You can’t do this easily with [Authorize(Roles="Admin,Author")]. Instead, ASP.NET Core provides Policies.

First, define the Policy in Program.cs:

builder.Services.AddAuthorization(options =>
{
    // Define a rule: You must be at least 18 AND have an employee badge!
    options.AddPolicy("MustBeAdultEmployee", policy =>
    {
        policy.RequireClaim("Age", "18", "19", "20", "21"); // Oversimplified!
        policy.RequireClaim("EmployeeBadge");
    });
});

Then, apply the Policy to the endpoint!

app.MapGet("/employee-lounge", () => "Welcome to the lounge.")
   .RequireAuthorization("MustBeAdultEmployee");

Challenge for Day 24

In yesterday’s JWT authentication setup, try modifying the app.MapGet requirement to use a custom policy. Define a policy in AddAuthorization(options => ...) that requires a specific claim like “Department” to equal “IT”. Mint a token with jwt.io containing that claim, and hit the endpoint!

Tomorrow: Configuration & Secrets Management (Hiding that JWT Key!).