Introduction
Authentication is the process of determining or giving individual access to system or user based on their identity. This article demonstrates how to add custom Policy-based & Role-based Authorization in ASP.NET Core 3.0
In the simple case of Authentication, we generally use the username and the password for login and based on that we are providing access to the application, but in this case, the user can access all the resources of the application. By using Policy-based & Role-based Authorization process, we can provide access to particular area of application to the user based on the Role/Policy of the user.
In this demonstration, I am going to use cookies to store user information. Readers can use a database to store user information.
Prerequisites
- Install .NET Core 3.0.0 or above SDK from here.
- Install the latest version of Visual Studio 2019 Community Edition from here.
Steps for creating a web application
Please check my existing article, Cookie Authentication In .NET Core 3.0 for project setup. Here I have explained step by step how to create project? and how to manage authentication?
Code for the Basic Authorization
If you want to add simple Authentication and want to define only Role/Policy with authorization tag for authorizing action/controller like in the below syntax, then you can go with simple configuration. AuthorizationPolicyBuilderclass helps you to achieve this requirement.
Add Authorize tag on controller with Policy/Role
- [Authorize(Policy = "UserPolicy")]
- [Authorize(Roles = "Admin")]
- public class HomeController : Controller
- {
- }
Add Authorize tag on action with Policy/Role
- [Authorize(Policy = "UserPolicy")]
- public ActionResult UsersPolicy()
- {
- var uses = new Users();
- return View("Users", uses.GetUsers());
- }
- [Authorize(Roles = "User")]
- public ActionResult UsersRole()
- {
- var uses = new Users();
- return View("Users", uses.GetUsers());
- }
Update Startup.cs file with below code
- using System.Security.Claims;
- using Microsoft.AspNetCore.Authorization;
- using Microsoft.AspNetCore.Builder;
- using Microsoft.AspNetCore.Hosting;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Hosting;
- namespace CookieAuthenticationDemo
- {
- public class Startup
- {
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
- public IConfiguration Configuration { get; }
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddAuthentication("CookieAuthentication")
- .AddCookie("CookieAuthentication", config =>
- {
- config.Cookie.Name = "UserLoginCookie"; // Name of cookie
- config.LoginPath = "/Login/UserLogin"; // Path for the redirect to user login page
- });
- services.AddAuthorization(config =>
- {
- var userAuthPolicyBuilder = new AuthorizationPolicyBuilder();
- config.DefaultPolicy = userAuthPolicyBuilder
- .RequireAuthenticatedUser()
- .RequireClaim(ClaimTypes.DateOfBirth)
- .Build();
- });
- 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?}");
- });
- }
- }
- }
Integrate Custom Authorization Handler
Step 1
Create a new folder with the name CustomHandler and add the below classes into it.
Class 1 - AuthorizationPolicyBuilderExtension: User defined static class for addding a new policy for Authorization using AuthorizationPolicyBuilder.
Class 2 - CustomUserRequireClaim: User defined class inherits from IAuthorizationRequirement interface. IAuthorizationRequirement interface does not contain any method. This is an empty marker service.
Class 3 - PoliciesAuthorizationHandler: User defined class inherits from AuthorizationHandler class. TheHandleRequirementAsync method of AuthorizationHandler class
helps to validate user based on policy.
Class 4 - RolesAuthorizationHandler: Same like PoliciesAuthorizationHandler class. This class helps to validate user based on Role.
Code for CustomUserRequireClaim: Put the below lines of code intoCustomUserRequireClaim class.
- using Microsoft.AspNetCore.Authorization;
- using System.Linq;
- using System.Threading.Tasks;
- namespace CookieAuthenticationDemo.CustomHandler
- {
- public class CustomUserRequireClaim : IAuthorizationRequirement
- {
- public string ClaimType { get; }
- public CustomUserRequireClaim(string claimType)
- {
- ClaimType = claimType;
- }
- }
- }
Code for AuthorizationPolicyBuilderExtension - Put the below lines of code intoAuthorizationPolicyBuilderExtension class.
- using Microsoft.AspNetCore.Authorization;
- namespace CookieAuthenticationDemo.CustomHandler
- {
- public static class AuthorizationPolicyBuilderExtension
- {
- public static AuthorizationPolicyBuilder UserRequireCustomClaim(this AuthorizationPolicyBuilder builder, string claimType)
- {
- builder.AddRequirements(new CustomUserRequireClaim(claimType));
- return builder;
- }
- }
- }
Code for PoliciesAuthorizationHandler - Put the below lines of code intoPoliciesAuthorizationHandler class.
- using Microsoft.AspNetCore.Authorization;
- using System.Linq;
- using System.Threading.Tasks;
- namespace CookieAuthenticationDemo.CustomHandler
- {
- public class PoliciesAuthorizationHandler : AuthorizationHandler<CustomUserRequireClaim>
- {
- protected override Task HandleRequirementAsync(
- AuthorizationHandlerContext context,
- CustomUserRequireClaim requirement)
- {
- if (context.User == null || !context.User.Identity.IsAuthenticated)
- {
- context.Fail();
- return Task.CompletedTask;
- }
- var hasClaim = context.User.Claims.Any(x => x.Type == requirement.ClaimType);
- if (hasClaim)
- {
- context.Succeed(requirement);
- return Task.CompletedTask;
- }
- context.Fail();
- return Task.CompletedTask;
- }
- }
- }
Code for RolesAuthorizationHandler - Put the below lines of code intoRolesAuthorizationHandler class.
- using CookieAuthenticationDemo.Models;
- using Microsoft.AspNetCore.Authorization;
- using Microsoft.AspNetCore.Authorization.Infrastructure;
- using System.Linq;
- using System.Threading.Tasks;
- namespace CookieAuthenticationDemo.CustomHandler
- {
- public class RolesAuthorizationHandler : AuthorizationHandler<RolesAuthorizationRequirement>, IAuthorizationHandler
- {
- protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
- RolesAuthorizationRequirement requirement)
- {
- if (context.User == null || !context.User.Identity.IsAuthenticated)
- {
- context.Fail();
- return Task.CompletedTask;
- }
- var validRole = false;
- if (requirement.AllowedRoles == null ||
- requirement.AllowedRoles.Any() == false)
- {
- validRole = true;
- }
- else
- {
- var claims = context.User.Claims;
- var userName = claims.FirstOrDefault(c => c.Type == "UserName").Value;
- var roles = requirement.AllowedRoles;
- validRole = new Users().GetUsers().Where(p => roles.Contains(p.Role) && p.UserName == userName).Any();
- }
- if (validRole)
- {
- context.Succeed(requirement);
- }
- else
- {
- context.Fail();
- }
- return Task.CompletedTask;
- }
- }
- }
Changes In Users class - Update Users class as I mentioned. I have added Role and DateOfBirth extra properties here.
- using System.Collections.Generic;
- namespace CookieAuthenticationDemo.Models
- {
- public class Users
- {
- public int Id { get; set; }
- public string UserName { get; set; }
- public string Name { get; set; }
- public string EmailId { get; set; }
- public string Password { get; set; }
- public string Role { get; set; }
- public string DateOfBirth { get; set; }
- public IEnumerable<Users> GetUsers()
- {
- return new List<Users>() { new Users { Id = 101, UserName = "anet", Name = "Anet", EmailId = "[email protected]", Password = "anet123", Role="Admin" , DateOfBirth = "01/01/2012"} };
- }
- }
- }






Hamid KhanPosted Jan 9, 2022, 4:21 PM
Very well explained
Faizan SyedPosted Jul 20, 2020, 1:48 AM
How to assigned attribute roles to requirement.AllowedRoles?
Renan BarbosaPosted Jun 2, 2020, 4:25 AM
How to show user name authenticated in navbar?
Prakash TripathiPosted Apr 20, 2020, 11:12 PM
Any example to do the same in core apis?
Rathrola Prem KumarPosted Feb 5, 2020, 1:42 AM
Great explanation , Keep rocking