Search This Blog

ASP.NET MVC Fine Grained Identity & Access Control - Part 1

In this series I will explain how I designed a generic claims based access control system ASP.NET MVC 5 with Identity 2.0.

Part 2: ASP.NET MVC Fine Grained Identity & Access Control - Part 2The method I explain here will be useful for applications with moderate complexity, which would require an end user (an admin) to define which resources a particular user has access to. Since I could not find any existing projects with what I want, I bootstrapped my own. I realized that a lot of people want to build something like this, but there are no available resources. Also, please, not that, there is a lot of room for improvement. I will be updating the github repo as I develop the blog post series.

This post targets moderate .NET skill sets. If you have no idea what a claim is, you should first go through that. And see how role based access works. And then come back to claims. Understand the difference and then come back to this post. Also, its nice if you do know what logic gates are. Most of the time, associations help us understand stuff better. Think gates!Jump right into code, if you know what you're doing. (I don't comment every line, I try to use self explanatory code. If you don't understand, shoot me a message.)This is a 5 part series where I explain in detail how I achieved fine grained access control in ASP.NET MVC 5 with Identity 2.0. 1. The approach & Features2. Database design considerations3. Lets do some coding - TODO4. Let the user pick who has access to what- TODO5. F5- TODO

The approach & FeaturesGitHub Repo: ClaimsAuthI'll try to keep this post simple and short. We have different kinds of users. (Employees, Agents, 3rd Party, Guest and so on.) Following are the (not finalized) requirements and approaches taken to visualize the end result.

The UI should change according to the logged in user type.

I need to be able to use this on both MVC and WebAPI end points.

Admins are not allowed to manually add routes/permission sets/ACLs. It should be system generated. Admins can only SELECT who has access to what. This is to eliminate human error. Imagine 100000 end points.

Users belong to one or more groups (Super Admin, Admin, Agent, Client etc.). Using the existing Role based model as a user group based model with claims, we can do some magic.

Administrators has access to almost everywhere and can create lower level users, but they can't assign permissions. Super admins can limit permissions of admins.

Other groups can see only what they are given.

Users can have special permissions. For example, Everyone in Agent group is denied access to updating a hotel, but a special agent who might also be the owner of a hotel can be given specific access to updating only their hotel.

Entire access control system runs on MVC area-controller-action sets. This authorization part is designed for a large complex system. Therefore we design the system hierarchically, where no one has no access (including super admins) and we gradually define which parts the groups/users has access to. And we give super admins and admins exclusive access through a claim. Access to everywhere is denied by default.

If a group is given access to an area, that group can access any controller/action within that group

If a group is given access to a controller, any action in the controller can be accessed.

If only an action level permission is given, the obvious thing happens, which is, the group has no access to anything else in that controller.

Groups doesn't have any special order, and if any of the groups the user belongs to has access to a required resource, user can access it. i.e., one group can deny access to Chat section but, another group, can grant it. Since, the user is in both groups, he gets to access chat section.

A system only grows. In order to maintain security, except for admins every new feature on the system is locked down to less fortunate users, unless super admin gives access to them.

Entire ACL is cached so the lookups can be faster.

Assumptions

I assume, that you know what C# is, and how to use Visual Studio 2012+.

I also assume that, you are here, because you want to know how to do something like this in your own/office/whatever project

I also assume you have moderate level of experience in C#

Another assumption is that, you know what claims are, what access control is, what system security is. Why we need security,

I also assume you know the difference between authentication and authorization.

You need to have an basic understanding of how the ASP.NET Identity framework works.

Also, you need to know SQL

And, you need to know how to work with EF (Entity Framework!)

Any previous experience in role based access management is a definite plus

If you are here because the title sounded cool, thanks, read on. You might learn something!

Database Design ConsiderationsI am not a fan of re-inventing the wheel, so I'll be piggybacking on the existing ASP.NET identity tables. And add the minimum no of tables I want, to get the job done. Not a fan of too-many-tables-than-necessary either. I'm gonna call every AREA-CONTROLLER-ACTION trio as resources in my system. WebAPI included. Area itself is a resource. Controller itself is a resource. Action itself is a resource. Any combination of them, is also a resource. I'll auto generate everything from the system itself. I have a multiple applications using the same database, so I need to know which user belongs to which application. This is the "Application" table.I also have different user types. An 'enum' in the system, just to make my life easier. This is the "Application User Type" table.There are parts of the system, that everyone MUST have access to. Like Login and Logout. Yeah, this can deny access to logout and login too. So, lets have a place for them. I'll call it "Resource Global Permissions". I like to have a "Allow All" bit field in this table so that I can quickly switch off if I change my mind about login, or whatever.Then there are every other resource, which can be given or denied access to. We'll put them in "Resource Role Permission" table. We'll assign roles to resources here. Also have a "Allow" bit field, so its easier to control if I ever change my mind about a user.
User Groups/Roles will be defined in "AspNetRoles" table. (Generated)We'll use the existing "Asp Net User Claims" table to store our claims. I'm not going to use a seperate table to store claims. There will not be redundancies because this table stores only special claims. Such as exclusive access claim for super admins. Allowed hotel ID for an agent, etc.Rest of the tables you can read about on here..

Initial database diagram

ASP.NET Identity 2.0 generated tables:

AspNetRoles

AspNetUserRoles

AspNetUsers

AspNetUserLogins => Not used here!

AspNetClaims

Now, we only have to add 5 more tables:

Application

ApplicationResource

ApplicationUserType

ResourceGlobalPermission

ResourceRolePermission

Even though I call it "Groups" instead of "Roles" I use the term Role here just to keep things not confusing.

I'm not going to define table structures here. You can find them in the source.

All the fields with "ID" in it are Ints

Every field with 'Is' in it are bits

'Active' is a bit field.

Every field which sounds like a boolean field, is a bit field.

Every field which sounds like a text field is a nvarchar field with appropriate lenghts.

CustomerID and EmployeeID in AspNetUsers table are there to differentiate between Agents and Employees. (You may not need that in yours)

Popular posts from this blog

If you have ever tried to build a POS (Point Of Sales or Point of Services) application, you might have come across the requirement to print a sales receipt like the following. Not just retail stores, but these receipts are produced by banks, hospitality and healthcare too.

Most of the time, such a receipt can be printed using a POS printer, which looks like the one below. The application developer needs to send ESC/POS commands to such a printer (eg: EPSON) to print the actual receipt. Depending on the manufacturer the capabilities can be vary. However, most of them can handle most of the print commands and print a nicely formatted receipt.

The main advantage of using raw ESC/POS commands for printing is that the printing performance will be faster but this depends on the printer itself.

In this post, I will be using a windows application to send commands to the printer. If you want to do this through a ASP.NET website, the process is a bit more complex and I will try to create anot…

Recently (Not so long ago, more like 10 mins ago) my asked me to automatically redirect the user to the login screen after session is expired. I googled it, found 2 ways. One works well with NON-AJAX websites and it is the simplest.

If you are making a site like facebook, then using the above method would cause number of users to decrease from 1 billion to 0. Why? because this method counts only full page refreshes, not ajax requests.

I am accessing a 3rd party client WCF secured web service using a client certificate issued by them. I have added this client certificate to my servers' certificate store. (Ref#1 (packing a certificate), Ref#2 (importing to store))