Thursday, July 18, 2024

Creating Authorization Policies in .NET Core 8.0

Authorization in .NET Core is a process that determines what a user is able to do. It uses policies to determine these permissions. Let’s dive into how to create authorization policies in .NET Core 8.0.

1. Defining Policies

Policies are defined in the Startup.cs file in the ConfigureServices method. Here’s an example of how to define a policy:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthorization(options =>
    {
        options.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"));
    });
}

In this example, we’ve created a policy named “AdminOnly” that only allows users in the “Admin” role to access certain resources.

2. Applying Policies

Once you’ve defined your policies, you can apply them to your controllers or action methods using the [Authorize] attribute. Here’s how:

[Authorize(Policy = "AdminOnly")]
public class AdminController : Controller
{
    // Controller methods here
}

In this example, only users who fulfill the “AdminOnly” policy (i.e., users in the “Admin” role) can access the methods in the AdminController.

3. Policy Requirements

Policies can also have multiple requirements. Here’s an example:

services.AddAuthorization(options =>
{
    options.AddPolicy("AgeRequirement", policy =>
        policy.Requirements.Add(new MinimumAgeRequirement(18)));
});

In this example, we’ve added an age requirement to our policy. We would also need to create a MinimumAgeRequirement class and a handler for this requirement.

public class MinimumAgeRequirement : IAuthorizationRequirement
{
    public int MinimumAge { get; }

    public MinimumAgeRequirement(int minimumAge)
    {
        MinimumAge = minimumAge;
    }
}

public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                   MinimumAgeRequirement requirement)
    {
        var dateOfBirth = DateTime.Parse(
            context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth).Value);

        var age = DateTime.Today.Year - dateOfBirth.Year;

        if (age >= requirement.MinimumAge)
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

In this example, the MinimumAgeRequirement specifies the age requirement, and the MinimumAgeHandler handles the requirement.

Remember, authorization policies are a powerful way to control access to your resources. Use them wisely to secure your application. 

You could add different kinds of policies based on Claim Types. Here are more examples.

1. Policy Based on Claim Type

You can create a policy based on a specific claim type. For example, you can create a policy that only allows users with a specific claim to access certain resources:

services.AddAuthorization(options =>
{
    options.AddPolicy("EmailClaimPolicy", policy =>
        policy.RequireClaim(ClaimTypes.Email));
});

In this example, only users with an email claim can access the resources protected by the “EmailClaimPolicy”.

2. Policy with Multiple Requirements

Policies can have multiple requirements. Here’s an example:

services.AddAuthorization(options =>
{
    options.AddPolicy("EmployeeOnly", policy =>
        policy.RequireRole("Employee")
              .RequireClaim("Department", "Sales", "Marketing"));
});

In this example, the “EmployeeOnly” policy requires the user to be in the “Employee” role and have a “Department” claim of either “Sales” or “Marketing”.

3. Custom Requirements

You can also create custom requirements. Here’s an example:

public class WeekendRequirement : IAuthorizationRequirement { }

public class WeekendRequirementHandler : AuthorizationHandler<WeekendRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                   WeekendRequirement requirement)
    {
        if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday ||
            DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

services.AddAuthorization(options =>
{
    options.AddPolicy("WeekendPolicy", policy =>
        policy.Requirements.Add(new WeekendRequirement()));
});

In this example, the “WeekendPolicy” only allows access on weekends.

Remember, the key to effective authorization is to create policies that accurately represent your business requirements. Happy coding!