Power of Authentication(Cookies) and Authorization(Role, Policy, Claim) in .NET
Authentication and authorization are fundamental aspects of securing applications. Authentication verifies a user’s identity, while authorization determines the resources and operations the authenticated user can access. In .NET, these concepts are powerful and flexible, enabling developers to implement secure and robust applications.
Embark on a journey of continuous learning and exploration with DotNet-FullStack-Dev. Uncover more by visiting our https://dotnet-fullstack-dev.blogspot.com reach out for further information.
Authentication
Authentication is the process of verifying the identity of a user or service. In .NET, authentication can be implemented using various methods such as cookies, JWT tokens, OAuth, and OpenID Connect.
Example: Implementing Cookie Authentication
Install NuGet Packages:
dotnet add package Microsoft.AspNetCore.Authentication.Cookies
Configure Services:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/Account/Login";
options.AccessDeniedPath = "/Account/AccessDenied";
});
services.AddControllersWithViews();
}
Configure Middleware:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
Login Action:
[HttpPost]
public async Task<IActionResult> Login(LoginModel model)
{
if (ModelState.IsValid)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, model.Username)
};
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties
{
IsPersistent = model.RememberMe
};
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties);
return RedirectToAction("Index", "Home");
}
return View(model);
}
Authorization
Authorization determines what resources and operations the authenticated user can access. .NET supports role-based authorization, policy-based authorization, and claims-based authorization.
Role-Based Authorization
Role-based authorization restricts access based on user roles.
Add Roles to Claims:
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, model.Username),
new Claim(ClaimTypes.Role, "Administrator")
};
Restrict Access by Role:
[Authorize(Roles = "Administrator")]
public IActionResult AdminOnly()
{
return View();
}
Policy-Based Authorization
Policy-based authorization allows defining policies with multiple requirements.
Configure Policies:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization(options =>
{
options.AddPolicy("AdminPolicy", policy => policy.RequireRole("Administrator"));
options.AddPolicy("Over18Policy", policy => policy.RequireClaim("Age", "18"));
});
services.AddControllersWithViews();
}
Apply Policies:
[Authorize(Policy = "AdminPolicy")]
public IActionResult AdminOnly()
{
return View();
}
Claims-Based Authorization
Claims-based authorization uses claims to make authorization decisions.
Add Claims:
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, model.Username),
new Claim("Age", "25")
};
Use Claims in Policies:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization(options =>
{
options.AddPolicy("Over18Policy", policy => policy.RequireClaim("Age", "18"));
});
services.AddControllersWithViews();
}
Apply Policies:
[Authorize(Policy = "Over18Policy")]
public IActionResult AdultsOnly()
{
return View();
}
Putting It All Together: Example Application
Startup.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/Account/Login";
options.AccessDeniedPath = "/Account/AccessDenied";
});
services.AddAuthorization(options =>
{
options.AddPolicy("AdminPolicy", policy => policy.RequireRole("Administrator"));
options.AddPolicy("Over18Policy", policy => policy.RequireClaim("Age", "18"));
});
services.AddControllersWithViews();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
AccountController.cs
public class AccountController : Controller
{
[HttpGet]
public IActionResult Login()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login(LoginModel model)
{
if (ModelState.IsValid)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, model.Username),
new Claim(ClaimTypes.Role, "Administrator"),
new Claim("Age", "25")
};
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties
{
IsPersistent = model.RememberMe
};
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties);
return RedirectToAction("Index", "Home");
}
return View(model);
}
[HttpPost]
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return RedirectToAction("Index", "Home");
}
}
HomeController.cs
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
[Authorize(Roles = "Administrator")]
public IActionResult AdminOnly()
{
return View();
}
[Authorize(Policy = "Over18Policy")]
public IActionResult AdultsOnly()
{
return View();
}
[Authorize]
public IActionResult SecurePage()
{
return View();
}
}
Conclusion
Authentication and authorization are crucial for securing applications. .NET provides powerful and flexible tools to implement various authentication methods and authorization schemes, such as role-based, policy-based, and claims-based authorization. By leveraging these tools, developers can build secure and robust applications tailored to their specific security requirements.
You may also like : https://medium.com/@siva.veeravarapu/role-based-authorization-in-net-core-a-beginners-guide-with-code-snippets-b952e5b952f7