ASP.NET Authentication and Authorization Fundamentals

This document provides a comprehensive overview of authentication and authorization mechanisms within ASP.NET applications. Understanding these concepts is crucial for building secure and robust web applications.

What are Authentication and Authorization?

Authentication is the process of verifying the identity of a user. It answers the question: "Who are you?". This is typically achieved by asking for credentials, such as a username and password, an API key, or a token.

Authorization is the process of determining whether an authenticated user has permission to perform a specific action or access a resource. It answers the question: "What are you allowed to do?". This is often based on roles, claims, or policies.

Key Concepts in ASP.NET

Authentication Methods

ASP.NET supports various authentication schemes:

Implementing Cookie Authentication

ASP.NET Core makes cookie authentication straightforward. You'll typically configure services in Startup.cs (or Program.cs in .NET 6+):


public void ConfigureServices(IServiceCollection services)
{
    // ... other services
    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie(options =>
        {
            options.LoginPath = "/Account/Login"; // Path to the login page
            options.LogoutPath = "/Account/Logout"; // Path to the logout page
            options.ExpireTimeSpan = TimeSpan.FromMinutes(30); // Session duration
        });

    services.AddAuthorization(); // Enables authorization policies
    // ...
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ...
    app.UseAuthentication(); // Must be called before UseAuthorization
    app.UseAuthorization();
    // ...
}
        

Authorization Strategies

Role-Based Authorization

Assign users to roles and grant access based on those roles. This is configured using the [Authorize] attribute.


[Authorize(Roles = "Admin,Editor")]
public class AdminController : Controller
{
    // ... actions
}
        

Or in Startup.cs for global or policy-based authorization.

Policy-Based Authorization

Policies provide a more flexible and powerful way to define authorization requirements. You define a policy with specific requirements and then apply it.


// In Startup.cs (ConfigureServices)
services.AddAuthorization(options =>
{
    options.AddPolicy("RequireAdminRole", policy => policy.RequireRole("Admin"));
    options.AddPolicy("MustBeEmployee", policy => policy.RequireClaim("EmployeeId"));
    options.AddPolicy("MinimumAgePolicy", policy => policy.RequireAssertion(context =>
    {
        var ageClaim = context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth);
        if (ageClaim == null) return false;

        var dob = DateTime.Parse(ageClaim.Value);
        var age = DateTime.Today.Year - dob.Year;
        if (dob.Date > DateTime.Today.AddYears(-age)) age--; // Adjust for birthday

        return age >= 18;
    }));
});
        

Applying a policy:


[Authorize(Policy = "MinimumAgePolicy")]
public IActionResult Profile()
{
    // ...
    return View();
}
        

Claims-Based Authorization

Authorization can be directly based on claims present in the user's identity.


[Authorize(Policy = "MustBeEmployee")]
public IActionResult EmployeeDashboard()
{
    // ...
    return View();
}
        
Important Note: The order of middleware in Configure is critical. UseAuthentication must run before UseAuthorization so that the user is authenticated before authorization checks are performed.

Security Best Practices

Further Reading