User Authentication and Authorization in C# .NET: A Comprehensive Guide

Introduction
User authentication and authorization are essential components of any web application, ensuring that users can securely access and interact with the system’s resources. In this comprehensive guide, we’ll explore how to implement user authentication and authorization in a C# .NET application using ASP.NET Core Identity. By the end of this article, you’ll have a solid understanding of how to build a secure authentication system with role-based access control (RBAC) in your C# .NET applications.
Setting Up ASP.NET Core Identity:
ASP.NET Core Identity is a membership system that adds login functionality to your application. It provides APIs for user authentication, registration, password management, and more. Let’s start by setting up ASP.NET Core Identity in our project.
- Install ASP.NET Core Identity:
- Open your C# .NET project in Visual Studio.
- Install the Microsoft.AspNetCore.Identity.EntityFrameworkCore package using NuGet Package Manager:
Install-Package Microsoft.AspNetCore.Identity.EntityFrameworkCore2. Configure Identity Services:
- In your Startup.cs file, add the following code inside the ConfigureServices method to configure ASP.NET Core Identity services:
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();Implementing User Registration:
Now that we’ve set up ASP.NET Core Identity, let’s implement user registration functionality in our application.
- Create Registration Endpoint:
- Create a new controller (e.g., AccountController) and add a Register action method to handle user registration requests.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new IdentityUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
return RedirectToAction("Index", "Home");
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
return View(model);
}2. Create Registration View:
- Create a view (e.g., Register.cshtml) to display the registration form and capture user input.
@model RegisterViewModel
<h2>Register</h2>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Register" method="post" class="form-horizontal" role="form">
<h4>Create a new account.</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Email" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Password" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="ConfirmPassword" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="ConfirmPassword" class="form-control" />
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="submit" class="btn btn-default">Register</button>
</div>
</div>
</form>
</div>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}Implementing User Login and Logout:
Next, let’s implement user login and logout functionality in our application.
- Create Login Endpoint:
- Add a Login action method to the AccountController to handle user login requests.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model)
{
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
return RedirectToAction("Index", "Home");
}
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}
return View(model);
}2. Create Logout Endpoint:
- Add a Logout action method to the AccountController to handle user logout requests.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout()
{
await _signInManager.SignOutAsync();
return RedirectToAction("Index", "Home");
}Role-Based Authorization:
Finally, let’s implement role-based authorization to control access to different parts of our application.
- Define Roles:
- Define roles (e.g., Admin, User) using the RoleManager service.
using Microsoft.AspNetCore.Identity;
public class Startup
{
// Other configuration methods omitted for brevity
public void Configure(IApplicationBuilder app, IHostingEnvironment env, RoleManager<IdentityRole> roleManager)
{
// EnsureRolesAsync will create the specified roles if they do not already exist
EnsureRolesAsync(roleManager).Wait();
// Other middleware configuration omitted for brevity
}
private async Task EnsureRolesAsync(RoleManager<IdentityRole> roleManager)
{
// Ensure that the "Admin" role exists
if (!await roleManager.RoleExistsAsync("Admin"))
{
var adminRole = new IdentityRole("Admin");
await roleManager.CreateAsync(adminRole);
}
// Ensure that the "User" role exists
if (!await roleManager.RoleExistsAsync("User"))
{
var userRole = new IdentityRole("User");
await roleManager.CreateAsync(userRole);
}
// Add more roles as needed
}
}2. Assign Roles to Users:
- Assign roles to users during registration or through an administrative interface.
using Microsoft.AspNetCore.Identity;
public class AccountController : Controller
{
private readonly UserManager<IdentityUser> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
public AccountController(UserManager<IdentityUser> userManager, RoleManager<IdentityRole> roleManager)
{
_userManager = userManager;
_roleManager = roleManager;
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new IdentityUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
// Assign role to user (e.g., "User")
await _userManager.AddToRoleAsync(user, "User");
// Redirect to the appropriate page after registration
return RedirectToAction("Index", "Home");
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
return View(model);
}
}3. Authorize Access:
- Add Authorize attributes to controller actions or action methods to restrict access based on user roles.
[Authorize(Roles = "Admin")]
public IActionResult AdminDashboard()
{
return View();
}Conclusion
By following this comprehensive guide, you’ve learned how to implement user authentication and authorization in a C# .NET application using ASP.NET Core Identity. With user registration, login/logout functionality, and role-based access control (RBAC) in place, your application is now equipped with a robust security system to protect its resources and ensure a secure user experience






