Role Based Authorization In Blazor

In this post, we will see how to add authentication and role-based authorization using identity framework in Blazor application.

Introduction


Blazor is a new framework built by Microsoft for creating interactive client-side web UI with .NET codebase. We can write both client-side and server-side code in C#.NET itself. I have already written six articles about Blazor server on C# Corner. Please refer to below articles for more basics about Blazor framework.
Microsoft provide identity framework for authentication and authorization in Blazor application by default. Please note, currently they are using MVC Core razor pages for authentication UI. They use “Microsoft.AspNetCore.Identity.UI” package library to achieve this. In future, they may replace this with Razor components. In this post, we can see how to add authentication and authorization for Blazor application and restrict pages with user roles. I will explain all these actions step by step.

Create a Blazor application in Visual Studio 2019 with authentication


Choose Blazor template in Visual Studio 2019 and click “change” option under authentication.
 
 
Choose “Individual User Accounts” type and keep default “Store user accounts in-app” to store SQL tables locally for identity framework.
 
 
 
After choosing the authentication type, you can click “Create” button to create the project.
 
If you check the NuGet package manager, you can see below packages are installed in the project automatically.
 
 
 
You can also notice that, a migration script file is created under “Migrations” folder along with “ApplicationDbContext” class file.
 
 
 
We can execute below Package Manager Console command to create SQL database and tables related to identity framework. If needed, you can modify the SQL connection string in appsettings.json file. By default, a unique database name is given in the appsettings.json file.
 
“update-database”
 
Above command will create a new database and seven tables in the database for identity user and roles.
 
 
We are not using all these seven tables in our Blazor application. We will use “AspNetUsers” table for storing user information. We will use “AspNetRoles” table for storing role information. We will also use “AspNetUserRoles” table to store role details for a user.
 
We can modify the “ConfigureServices” method in “Startup” class with below change. So that we can control the authorization with identity roles in the application.
 
 
 
ConfigureServices method in Startup class
  1. public void ConfigureServices(IServiceCollection services)  
  2.         {  
  3.             services.AddDbContext<ApplicationDbContext>(options =>  
  4.                 options.UseSqlServer(  
  5.                     Configuration.GetConnectionString("DefaultConnection")));  
  6.             services.AddDefaultIdentity<IdentityUser>()  
  7.                 .AddRoles<IdentityRole>()  
  8.                 .AddEntityFrameworkStores<ApplicationDbContext>();  
  9.             services.AddRazorPages();  
  10.             services.AddServerSideBlazor();  
  11.             services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();  
  12.             services.AddSingleton<WeatherForecastService>();  
  13.         }  
We can run the application and create two different users by clicking register button. By default, no roles will be added for these users. We will add different role for each user.
 
 
 
We can create a new user by clicking “Register” button.
 
 
We have created a new user “adminuser@gmail.com” as username. We can create one more user “normaluser@gmail.com”. Currently no roles are created. We can add two roles “Admin” and “Normal” into the table “AspNetRoles”.
 
 
We can add user roles into the table “AspNetUserRoles”. We need user id along with role id. You can copy the corresponding user id from AspNetUsers table.
 
 
 
 
I have added first user with admin role id and second user with normal role id.
We can create two Razor components “Admin” and “Normal” inside the “Pages” folder. The Admin component will be accessible for admin users and the Normal component will be accessible for both admin and normal users. We must decorate these components with Authorize attribute later.
 
 
We can create second component “Normal” in the same way.
 
Modify the shared component “NavMenu” with below changes. So that, these new components will be visible only for authorized users.
 
 
 
NavMenu.razor
  1. <div class="top-row pl-4 navbar navbar-dark">  
  2.     <a class="navbar-brand" href="">BlazorAuth</a>  
  3.     <button class="navbar-toggler" @onclick="ToggleNavMenu">  
  4.         <span class="navbar-toggler-icon"></span>  
  5.     </button>  
  6. </div>  
  7.   
  8. <div class="@NavMenuCssClass" @onclick="ToggleNavMenu">  
  9.     <ul class="nav flex-column">  
  10.         <li class="nav-item px-3">  
  11.             <NavLink class="nav-link" href="" Match="NavLinkMatch.All">  
  12.                 <span class="oi oi-home" aria-hidden="true"></span> Home  
  13.             </NavLink>  
  14.         </li>  
  15.         <li class="nav-item px-3">  
  16.             <NavLink class="nav-link" href="counter">  
  17.                 <span class="oi oi-plus" aria-hidden="true"></span> Counter  
  18.             </NavLink>  
  19.         </li>  
  20.         <li class="nav-item px-3">  
  21.             <NavLink class="nav-link" href="fetchdata">  
  22.                 <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data  
  23.             </NavLink>  
  24.         </li>  
  25.         <AuthorizeView Roles="Admin">  
  26.             <li class="nav-item px-3">  
  27.                 <NavLink class="nav-link" href="admin">  
  28.                     <span class="oi oi-list-rich" aria-hidden="true"></span> Admin Component  
  29.                 </NavLink>  
  30.             </li>  
  31.         </AuthorizeView>  
  32.         <AuthorizeView Roles="Admin, Normal">  
  33.             <li class="nav-item px-3">  
  34.                 <NavLink class="nav-link" href="normal">  
  35.                     <span class="oi oi-list-rich" aria-hidden="true"></span> Normal Component  
  36.                 </NavLink>  
  37.             </li>  
  38.         </AuthorizeView>  
  39.     </ul>  
  40. </div>  
  41.   
  42. @code {  
  43.     bool collapseNavMenu = true;  
  44.   
  45.     string NavMenuCssClass => collapseNavMenu ? "collapse" : null;  
  46.   
  47.     void ToggleNavMenu()  
  48.     {  
  49.         collapseNavMenu = !collapseNavMenu;  
  50.     }  
  51. }  
I have modified above component with a Blazor attribute “AuthorizeView” along with “Roles” property. First NavLink is assigned with Admin role and second NavLink is assigned with Admin and Normal roles. Hence, this link will be visible for both Admin and Normal users. Run the application again and login as admin user.
 
 
 
We can notice that, the navigation links for Admin component and Normal component are visible for this admin user. If you login with normal user, only Normal component link will be visible. You can notice one important thing that even without login, these two components are accessible via direct page route. We have not yet restricted these components. We can use “Authorize” attribute to restrict these components for authorized users.
 
We can modify the Admin component with below changes.
 
 
 
We have added Authorize attribute along with Roles property in this component.
 
Admin.razor
  1. @page "/admin"  
  2.   
  3. @attribute [Authorize(Roles = "Admin")]  
  4.   
  5. <h3>Admin Component</h3>  
  6.   
  7. <p>This page is only accessible to users with 'Admin' roles</p>  
  8.   
  9. @code {  
  10.   
  11. }  
We can modify the Normal component with below changes.
 
Normal.razor
  1. @page "/normal"  
  2.   
  3. @attribute [Authorize(Roles = "Admin, Normal")]  
  4.   
  5. <h3>Normal Component</h3>  
  6.   
  7. <p>This page is only accessible to users with 'Admin' or 'Normal' roles</p>  
  8.   
  9. @code {  
  10.   
  11. }  
In above component, we have decorated Authorize attribute with both Admin and Normal roles.
Run the application again as normal user and try to access Admin component by directly entering the route in the browser.
 
 
 
You will get an unauthorized access error message in the page. We have successfully implemented role-based authorization in two components.

Conclusion


In this post, we have seen how to create a Blazor application with individual user account authentication. We have created all the seven tables for identity framework using entity framework database migration. Later, we have added two different identity users by clicking register button in the application. We have added two roles Admin and Normal manually to the table. We have also added user roles into the other table with corresponding user id and role id. We have added authorization attribute in the NavMenu component to control the visibility of components with corresponding roles. We have decorated Admin and Normal components with Authorize attribute and Roles property to restrict unauthorized access to these components. This is only a basic application to show authentication and authorization in Blazor app. I will create more real projects with authentication and custom authorization in forthcoming days. Please feel free to share your valuable feedback about this post.