Role-Based Authorization in ASP.NET Core MVC

Role-Based Authorization in ASP.NET Core MVC

This blog is going to explain what Role-Based Authorization is and how it can be implemented in ASP.NET Core MVC. The Authorization is a process of controlling which page the logged-in user can access. Role-Based Authorization authorizes the user based on the user's roles.

Let's see how to achieve it step by step.

Step 1:
The first step is to make sure that the Authorization middleware is included in the Configure method of Startup.cs file. Authentication middleware checks whether the user has permission to place a request for the application. If the user has permission then it will allow creating a response. Authorization middleware should come after Authentication middleware as shown in the code below.

Startup.cs
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
   ...
   ...
   ...

    app.UseAuthentication();
    app.UseAuthorization();

   ...
   ...
   ...
}

Step 2:
In this step, I have created the Users class. It has three attributes: UserName, Password and Role. It also has a method called GetUsers(). For the purpose of the demo, I have included the details of some users. But for real use, you need to get user details from the database. In the two users, one of the user role is Admin another one is Guest.

Users.cs
public class Users
{
    public string Username { get; set; }
    public string Password { get; set; }
    public string Role { get; set; }

    public IEnumerable<Users> GetUsers()
    {
        return new List<Users>() { new Users { Username = "peter", Password = "123", Role="Admin" },
                                   new Users { Username = "parker", Password = "456", Role="Guest" }
    };
    }
}

Step 3:
This step is a controller step. Here the simple cookie authentication is implemented for authentication. In the login action method, the user role is added to the Claim list. Also, I added the AccessDenied action method to display an access denied message page to a user who attempts to access the page without an admin role. Finally, the Logout method added to logout the application.

AccountController.cs
public class AccountController : Controller
{
    [HttpGet]
    public ActionResult Login()
    {
        Users user = new Users();
        return View(user);
    }

    [HttpPost]
    public async Task<ActionResult> Login(Users user)
    {
        var usrs = new Users();
        var result = usrs.GetUsers().FirstOrDefault(u => u.Username == user.Username && u.Password == user.Password);
        if (result != null) 
        {
            var userClaims = new List<Claim>()
                        {
                        new Claim(ClaimTypes.Name, result.Username),
                        new Claim(ClaimTypes.Role, result.Role),
                        };

            var identity = new ClaimsIdentity(userClaims, CookieAuthenticationDefaults.AuthenticationScheme);

            var userPrincipal = new ClaimsPrincipal(new[] { identity });

            await HttpContext.SignInAsync(userPrincipal);

            return RedirectToAction("Index", "Home");
        }

        return View(user);
    }

    public ActionResult AccessDenied()
    {
        return View();
    }

    public async Task<ActionResult> Logout()
    {
        await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
        return RedirectToAction("Login", new Users());
    }
}

The following is the Home controller code. You can see the AdminPage() action method decorate with the Authorize attribute with the Roles property. So this page only allows users with an Admin role.

HomeController.cs
public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    [Authorize(Roles = "Admin")]
    public IActionResult AdminPage()
    {
        return View();
    }
}

In the example above, the [Authorize] attribute is added to the method. But you can also add the [Authorize] attribute at the controller level. So it applies to all action methods in the controller.

[Authorize(Roles = "Admin")]
public class HomeController : Controller
{
 ...
 ...
 ...
}

Step 4:
The final step is a view. I have added three views here, the first one is an Index view. This page will be displayed as soon as the user logs into the application. And it has a link (Anchor Tag Helper) with the text 'Only admin access the page'. When the user clicks on the link, the user with the Admin role will be redirected to the admin page otherwise, it will be redirected to the AccessDenied page.

Home/Index.cshtml
<a asp-controller="Home" asp-action="AdminPage">Only admin access the page</a>

Home/AdminPage.cshtml
<h4>Hi Admin!!!</h4>
<a asp-controller="Account" asp-action="Logout">Logout</a>

Account/AccessDenied.cshtml
<h4>Access Denied </h4>

Output 

If user peter logs in as Admin role, that user will be able to access the admin page. If a user who does not have an admin role logs in, the user is redirected to the denied page.

I hope this helps you. Keep coding.

Comments

Popular posts from this blog

Entity Framework Core (EF) with SQL Server LocalDB

Exploring EventCallback in Blazor: Building Interactive Components

A Step-by-Step Guide to Implementing Identity in ASP.NET Core MVC