Show or Hide Navigation Menus Based on User Role in ASP.NET Core Identity

How to Show or Hide Navigation Menus Based on User Role in ASP.NET Core Identity

In this article, I will discuss How to Show or Hide Navigation Menus Based on User Role using ASP.NET Core Identity. Please read our previous article discussing ASP.NET Core Identity Role-Based Authorization.

How do we show or hide the navigation menus based on the user role in the ASP.NET Core Identity?

We need to implement role-based authorization in views to show or hide the navigation menu based on user roles in the ASP.NET Core application using Identity.

Before proceeding further, please ensure you have set up roles in your application. Roles are typically defined in your database and assigned to users. You can create roles like Admin, Moderator, User, etc., and assign these roles to users upon registration or through an admin panel.

You can then check the user’s role in rendering the navigation menu items in Views conditionally. For example, we need to use the User.IsInRole(“RoleName”) method to determine if the current user belongs to a specific role as follows:

@if (SignInManager.IsSignedIn(User) && User.IsInRole("Admin"))
{
    <!-- Admin specific navigation items -->
}

@if (SignInManager.IsSignedIn(User) && User.IsInRole("User"))
{
    <!-- Standard user navigation items -->
}

Note: Even though you are implementing the Role-based Authorization in Views to show and hide navigation menus, it is always advisable to implement security on the Controller and actions.

ASP.NET Core Identity IsSignedIn Method

The IsSignedIn method of the SignInManager class checks if the current user is signed in. This method is useful in scenarios where we need to verify a user’s authentication status and display certain UI elements only to authenticated users.

Method Signature: public static bool IsSignedIn(ClaimsPrincipal principal)

Parameters
  • ClaimsPrincipal principal: This is the user principal, typically obtained from the current HTTP context in a web application. The ClaimsPrincipal represents the current user and contains all their claims, including identity claims.
Return Value
  • bool: The method returns a boolean value. It returns true if the user represented by the given ClaimsPrincipal is signed in; otherwise, it returns false.
ASP.NET Core Identity IsInRole Method

The IsInRole method determines whether the current user is in a specified role. This is useful for role-based authorization in your application. 

Method Signature: public virtual bool IsInRole(string role)

Parameters:
  • role: The name of the role to check.
Return Type:
  • bool: Returns true if the current user is in the specified role; otherwise, false.
Example to Understand How to Show or Hide Navigation Menu Based on User Role in ASP.NET Core

Let us see an example of how to show or hide menus based on role using ASP.NET Core Identity. If the logged-in user is in an Admin role, we want to display the Manage Roles navigation menu item as shown in the image below. This Manage Roles navigation menu will open the ListRoles view of AdministrationController, where the admin will manage the roles, like creating roles, updating roles, deleting roles, and adding or removing users from a role.

Example to Understand How to Show or Hide Navigation Menu Based on User Role in ASP.NET Core

If the logged-in user IS NOT in the Admin role, then the Manage Roles navigation menu item should not be displayed.

How to Show or Hide Navigation Menu Based on User Role in ASP.NET Core Identity

How to Show or Hide Navigation Menu based on Logged-in User Role?

The navigation menus are in the layout view (_Layout.cshtml). Please modify the _Layout.cshtml view file. Here, we inject the SignInManager service into the layout view using the @inject directive. Using the SignInManager service, we are checking whether the user is logged in using the IsSignedIn() method and checking the logged-in user’s role using the IsInRole() method if the user is in the Admin role.

@using Microsoft.AspNetCore.Identity
@inject SignInManager<ApplicationUser> SignInManager

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - ASPNETCoreIdentityDemo</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/ASPNETCoreIdentityDemo.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container-fluid">
                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                       
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>

                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="SecureMethod">Secure</a>
                        </li>

                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="NonSecureMethod">Non Secure</a>
                        </li>

                        @if (SignInManager.IsSignedIn(User) && User.IsInRole("Admin"))
                        {
                            <li class="nav-item">
                                <a class="nav-link text-dark" asp-controller="Administration" asp-action="ListRoles">
                                    Manage Roles
                                </a>
                            </li>
                        }
                    </ul>
                    <ul class="navbar-nav ml-auto">
                        @*If the user is signed-in display Logout link*@
                        @if (SignInManager.IsSignedIn(User))
                        {
                            <li class="nav-item">
                                <form method="post" asp-controller="account" asp-action="logout">
                                    <button type="submit" style="width:auto"
                                            class="nav-link btn btn-link py-0">
                                        Logout @User?.Identity?.Name
                                    </button>
                                </form>
                            </li>
                        }
                        else
                        {
                            <li class="nav-item">
                                <a class="nav-link text-dark" asp-controller="account" asp-action="register">
                                    Register
                                </a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link text-dark" asp-controller="account" asp-action="login">
                                    Login
                                </a>
                            </li>
                        }
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2023 - ASPNETCoreIdentityDemo - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
    <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    @await RenderSectionAsync("Scripts", required: false)

</body>
</html>

With the above changes in place, run the application, and it should work as expected.

What if the user types the URL in the address bar?

The URL for the Manage Roles navigation menu item is /Administration/ListRoles. What if the user types this URL directly in the address bar?

The Authorize attribute on the AdministrationController protects against unauthorized access. If the logged-in user is not in an Admin role, ASP.NET Core automatically redirects the user to the /Account/AccessDenied page, as shown in the image below. Our application doesn’t have a /Account/AccessDenied view, so it is showing a 404 error page.

What if the user types the URL in the address bar?

Creating AccessDenied Action in AccountController

Please add the following HttpGet AccessDenied() action method within the AccountController. We want this action method to be accessed by everyone, so we are decorating it with the AllowAnonymous Attribute.

[HttpGet]
[AllowAnonymous]
public IActionResult AccessDenied()
{
    return View();
}
Adding the AccessDenied View

Next, create a view named AccessDenied.cshtml within the /Views/Account directory and then copy and paste the following code:

@{
    ViewData["Title"] = "AccessDenied";
}

<div class="text-center">
    <h1 class="text-danger">Access Denied</h1>
    <h6 class="text-danger">You do not have Permission to view this resource</h6>
    <img src="~/Images/AccessDenied.png" style="height:300px; width:300px" />
</div>

Create a folder with the name Images within the wwwroot folder and then add the following image with the name AccessDenied.png.

Creating AccessDenied Action and Views in AccountController

Once you add the image, your folder structure should look as shown below:

How to Show or Hide Navigation Menu Based on User Role in ASP.NET Core Identity

With the above changes in place, run the application and access the /Administration/ListRoles URL with the User, which does not belong to the Admin Role, and you will see the following Error page.

How to Show or Hide Navigation Menu Based on User Role in ASP.NET Core Identity

How does Authorize Attribute know to redirect to AccountController AccessDenied Action?

In ASP.NET Core Identity, the [Authorize] attribute enforces access control on controllers and action methods, ensuring that only authenticated users or users with specific roles or policies can access them. When an unauthorized user attempts to access a resource protected by this attribute, the ASP.NET Core Framework redirects the user to a specified access denied path, typically handled by the AccountController.

By default, the path for unauthenticated users is /Account/AccessDenied, but you can also change this default access denied path. We configure the login path in the same way we can configure the Access Denied path within the Program.cs class file, as follows. Here, we need to use the AccessDeniedPath property of the CookieAuthenticationOptions object.

// Configure the Application Cookie settings
builder.Services.ConfigureApplicationCookie(options =>
{
    // If the LoginPath isn't set, ASP.NET Core defaults the path to /Account/Login.
    options.LoginPath = "/Account/Login"; // Set your login path here

    // If the AccessDenied isn't set, ASP.NET Core defaults the path to /Account/AccessDenied
    options.AccessDeniedPath = "/Account/AccessDenied"; // Set your access denied path here
});

In the next article, I will discuss How to Display All Users from the ASP.NET Core Identity Database. In this article, I explain How to Show or Hide the Navigation Menus Based on User Role in ASP.NET Core Identity. I hope you enjoy this article, How to Show or Hide Navigation Menu Based on User Role in ASP.NET Core Identity.

Leave a Reply

Your email address will not be published. Required fields are marked *