Implementing your own simple Roles mechanism in Delphi MVC Framework

Important Note: DMVC already has a Roles framework in place which is quite sophisticated and you can find it in the samples. My purpose of writing this blog is to demystify the subject by explaining it conceptually and then implementing it with bare hands so that you can understand the functionality of it all. In other words, this article is for the reader to understand what is the role of roles 😉 in the system. At the end of this blog, you will have a working (albeit simple) implementation of roles. You may then choose to discard it and use the one that comes with DMVC or continue using this one. The choice is yours. You may also want to extend this mechanism into your own choice of framework such as RAD Server, MARS, mORMot, etc.

That being said… let us now delve into why we need roles first. We will then talk about how to get it done.

Roles are important in more ways than meets the eye. The first and main aspect of implementing roles is security. When a logged in user is assigned a role, our system can automatically figure out what is and is not available to the user based on the role they belong to. This means access to certain functionality can be implicitly controlled by building rules in the system itself. Implementation of roles based access stream lines access control of end points. It also forces the programmer to assign a role (depending on the way you code of course) to every end point thereby ensuring that every end point is secure.

Now that you understand why roles are important in any serious rest service application, lets talk a bit about how we will go about implementing it

In the current context, what we are aiming to do is that when a user logs in, the system figures out the role the user belongs to and stores that role value in a session variable. From then on wards, every time the user makes any API call, we want our system to verify if the logged in user is allowed to make that API call. Simple? Great!

Enter…. Middleware!

Why middleware? Because role verification is a system wide requirement, it just makes sense to make a middleware of it so that we can add it to any and all services by simply using the unit.

The first thing we want to do is create some sort of a storage mechanism for the endpoints that are allowed / disallowed for a particular role. Remember, there are many ways to do this. I have chosen TDictionary because I think its the simplest to use and explain (which is the point of this blog anyway).

In the unit common to all your services, you can declare the following variable and create it in the unit’s initialisation:

Now that you have a place to store your role access control, we use this unit in one of our controller. We use the initialization section to add what roles are allowed what endpoints.

The important thing here to notice is the initialisation section. The format of the key string is useful and as per the information the middleware (explained later) will give us. For every kind of role (currently hard coded as 'Manager', 'User', 'Staff') we have simply added a comma separated value of the method name in our controller class. This basically will tell our roles middleware that a user having a role, say of Staff, has access only to the ListProjects and ProjectsStats method. For now, we are simply storing this information. Nothing else.

Next, we want to store the role in a session variable at the time of login. Here’s a sample of the login end point:

Now that we have the role in the session, next, we create a new middleware. I simply copied an existing one and emptied the implementation and added my code as follows:

The OnBeforeControllerAction is a called automatically before the end point is called. There we pass the full controller name along with its unit name , the end point name that is called by the client and the session’s Role variable to our method ValidateRole – whose job is to check if the end point is allowed to be called by the user role. If the method returns False, we raise an error which automatically is rendered to the client.

We implement the ValidateRole method as follows:

The above method looks up the UserRoles dictionary (the one we created right at the beginning and added bunch of values in the controller initialization, remember?) and searches for the text matching our controller class and user role. Once it finds it, it will search for the end point name that been called by the client. If that end point name is NOT present as part of the comma separated value, the method will return False triggering the exception.

That’s all there is to it.

2 Replies to “Implementing your own simple Roles mechanism in Delphi MVC Framework”

  1. I’m leaving my comment a little late here. I’ve done something similar but I created a custom attribute to decorate the methods. The middleware then checks the the role in the attribute on the method. The end effect is the same but the code is more readable as the role/permissions are tagged to the method.

Leave a Reply

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