Power of Authentication(Cookies) and Authorization(Role, Policy, Claim) in .NET

DotNet Full Stack Dev
3 min readJul 20, 2024

--

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

--

--

DotNet Full Stack Dev
DotNet Full Stack Dev

Written by DotNet Full Stack Dev

Join me to master .NET Full Stack Development & boost your skills by 1% daily with insights, examples, and techniques! https://dotnet-fullstack-dev.blogspot.com

No responses yet