Implementing Multiple User Roles with Role-Based Authorization in Dotvvm — Part One

Vincent Nwonah
DotVVM
Published in
7 min readApr 22, 2020
DotVVM logo

Introduction

Authorization is often confused with Authentication especially with beginners learning about both concepts for the first time. Let’s look at what they are.

We will build a simple Leave Request Application in Dotvvm for employees to request for leave, and HR can approve or deny these requests.

Authentication

Authentication involves protecting your application from unauthorized access. The most common way of achieving this for most websites is to mandate all users using the website to create an account and get access to the site using a username/email and password.

Authentication tells us who is using our application at a point in time and what they are doing, if an order is made on a product on an ecommerce site, we know from which user that order is coming from and can pull up their delivery details.

Authentication prevents anonymous people from using or access our web application.

Authorization

Authorization is often discussed after authentication because authentication first must be in place before we can do authorization. Authorization asks the question: does an authenticated user have the right to perform this action?

In an ecommerce application for example, there are regular users who browse and order items, then there are the site managers who check the order requests and forward these requests to the appropriate merchants.

Since regular users (or shoppers) should not have access to these order requests available to the site managers, we need to find a way to make sure that even if they somehow navigate to the URL of a dashboard showing these requests, they are denied access.

The way to enforce this is referred to Authorization.

Simply put; authorization is used to deny or grant certain classes of users access to certain parts of an application.

Authentication and Authorization in Dotvvm

As stated in the introductory section, we will be building a fully function Leave Request Application in DotVVM.

The application enforces authentication, meaning all users must have an account, created by the system admin when they join the company.

This application will have three roles:

Employee

Human Resource Personnel, and

System Administrator

System Administrators will be able to Create and Delete users from the system as people join the company. They will also be able to assign roles to employees and revoke these roles as necessary.

Human Resources Personnel will be able to view Leave Requests and either approve or reject them.

Employees are simply able to create leave requests and check if these requests are approved or denied.

Note that a system admin will not be able to access the approve or reject functionality, and the HR cannot create new users, this is us using authorization to enforce users to do only what they should.

Creating a new Dotvvm Project

To follow along; If you don’t already have the Dotvvm Templates installed in Visual studio, head to the Visual Studio Marketplace and search for “Dotvvm”, install the template for your Visual Studio version.

We begin by creating a new Dotvvm Web Application (.Net Core) named DotvvmLeaveRequestApplication (or any name you decide). On the options screen, select “Add Bootstrap 3”. Leave all other options blank so we are starting from a relatively empty project and adding everything ourselves. Click “Create Project”.

Run the project, at this point you should see a bold “Welcome to Dotvvm on the screen”

Configuring a Database to Hold our Application Data

Since we are storing user details, leave requests details and other necessary data, we will need a database. For the purpose of this demo application, we will be using entity framework’s in memory database. This provides the convenience of not having to generate and run migrations while we work.

Follow the steps below to configure an in-memory database.

Add the Microsoft.EntityFrameworkCore.InMemory NuGet package to the project.

Create a Folder named Data and a class named ApplicationDbContext in the Folder. This will server as our Database Context class. Add the code below to the class.

Ap;licationDbContext.cs

Next register our database context class in Startup.cs by adding the lines of code below to the ConfigureServices method.

Configure Application for Auth

Now that we have a database to store application data, we proceed to add Authentication

Add these Nuget Packages to the project; Microsoft.AspNetCore.Authentication.Cookies, Microsoft.AspNetCore.Identity, Microsoft.AspNetCore.Identity.EntityFrameworkCore

These nugets add the Asp.NetCore Identity package to our Application. Asp.Net Core Identity will manage authentication, database creation, user management, etc

We need toconfigure our database context class to generate database tables for Asp.Net Core. Open the ApplicationDbContext class and change

public class ApplicationDbContext : DbContext

to

public class ApplicationDbContext : IdentityDbContext

This simple change will tell our DbContext class to create tables to store user data when we create and run migrations.

Now open Startup.cs and add the lines of code below to Configure Services method

This bit of code tells DotVVM that we will be managing users in this application, configures our signin page path, and adds cookies that tell our application who is currently performing an action.

It also configures authorization (see IdentityRole), making functionality required to create and manage roles available to the application.

Creating User Roles and a Default System User

Our application will not have a signup page since employee accounts needs to be created by an admin, how then will the first admin account be created? We will create a user automatically on startup and assign the System Admin role to them.

Add the methods below to the Startup.cs class

The first method checks if the roles already exists in our database and creates them if they don’t. The second one checks if the default user has already been created and adds it if it hasn’t.

To use these methods, modify the Configure method in Startup.cs to accept a service provider parameter and call the added methods as shown below. Also note the call to app.UseAuthentication(); which tells the application that some pages will be protected.

Build and run the application, if you can see the same page from before, with no errors, we know everything is well configured.

Adding a Sign in Page

Since we have a default system user, we will now create a sign in page. This page will serve as the entry point for all employees, sys admins and human resource personnel.

Add a Services Folder and a class named UserService.cs. This services class will hold functionality related to user creation, signin, etc. Add the code below to the class

The first method checks that a user exists with the specified username and password, it returns null if the user doesn’t exist and the user’s claims if the user does.

The second method gets the details of the user and returns them in a claims identity object. We see that we are adding the user’s roles to this object. It can be inferred from here that a user can belong to multiple roles.

Register this service class in Startup.cs by adding services.AddTransient(typeof(UserService)); in ConfigureServices();

Now add a Folder named Authentication in the Views Folder, and a Dotvvm Page named SignIn.dothtml, a prompt asks if a master page should be use, accept it, also allow the prompt create a SignInViewModel class in ViewModels/Authenication. Add the code below to this class.

This class serves as view model for our Signin Page. The single method tries to validate the user and redirects them to the default page on successful login, or returns an error.

Return to Views/Authentication/Signin and add the DotVVM markup code below

In the above markup, we have two DotVVM textboxes for username and password and corresponding validators that display errors on invalid input. We also have a button that calls the SignIn method on the ViewModel class. Build and run the project, you notice we still go to our default page.

Let’s protect that page from unauthorized access by first adding the using statement `using DotVVM.Framework.Runtime.Filters;` to the DefaultViewModel class, then add the [Authorize] attribute to the class.

Running your application now should redirect you to sign in as only authenticated users can see the Default page.

If you still get to the Default page, this is probably because when testing the sign in page, you entered valid details and hit sign in, this mean you have an active session. Let us add a sign out button so users can sign out and back in.

To add a sign out button, open the MasterPage.dothtml file in in Views Folder and edit the markup to look like below

The code above adds a header to our MasterPage. We are using the DotVVM AuthenticatedView control. It provides two templates: AuthenticatedTemplate and NotAuthenticatedTemplate. The markup in AuthenticatedTemplate is displayed when a user is logged in, you see that we are adding a signout button which will be displayed when the user is logged in. We have added a signin button to be displayed when the user is logged out that simply redirects to the sign in page.

Open ViewModels/MasterPageViewModel.cs and add the method below

This method adds the sign out functionality which is called when the view button is called. Rebuild the project and run the application. You should be able to signin and signout now.

Conclusion

We have successfully added authentication to a DotVVM Web Application from scratch. In the next section, we will continue to build out other parts of our Leave Management Application by adding functionalities for employee creation, leave requests and approval/denial. See you there!

--

--