Using Role Based Access Control in the .NET Framework - Part 1

Hi Vineet Batta here..

Consider a scenario where you want to write an assembly which contains methods that only certain type of users can call (domain\Administrators or a specific custom users account). So how can we control this within code and let the runtime enforce these security checks?

Example scenario:

    1: public Class MyApplication
    2: {
    3: // You want that this method should only be called by users who are in domain\SuperUser account.
    4: // You want to restrict the access by runtime.
    5: public void UpdateUserProfile(int empId)
    6: {
    7: -- code to implement feature.
    8: }
    9: }

 

This is where Role Based Access Control (aka RBAC) can be effectively implemented. There are generally two ways to implement RBAC using either an  imperative or declarative method.  When we use declarative demands, we can require the user meet certain criteria before the runtime will execute the method. If the user lacks the permission, the runtime will throw the error which we can react to. Today, I will focus on declarative style and show case how easy it is achieve this and in part 2 well cover the imperative method.

 

First lets discuss about few classes.

System.Security.Permission.PrinicpalPermission class and the related System.Security.Permission.PrinicpalPermissionAttribute class will enable you to check active principal (aka USER account information) under which the runtime will execute the code. PrinicpalPermission can be used to demand that the identity of the active principal match this information.

PrinicpalPermission has three core properties :

  • Authentication : A boolean value. if this is set to true, the permission requires the user to be authenticated.
  • Name : The string that matches the identity of the user.
  • Role   : The string that must match one of the principal's role.

One of the most used methods is PrinicpalPermission.Demand(). It does the heavy lifting for us and you will see it in action in a sec...

To use declarative RBAC demands, we must complete the following three steps:

  1. Add the following code to specify principal security policy.

Example:

    1: System.AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);

    2. A Try/Catch block to catch underprivileged access attempts and to report errors.

    3. Annotate the method with PrinicpalPermission attribute to declare method's access requirements.

Complete Example:

    1:  
    2: void main()
    3: {
    4:  
    5: // Step 1.
    6: System.AppDomain.CurrentDomain.SetPrincipalPoilicy(PrincipalPoilicy.WindowsPrincipal);
    7:  
    8: //Step 2.
    9: try
   10: {
   11:  
   12: myApplication app = new myApplication();
   13:  
   14: // call the method for which RBS has be declared.
   15: app.UpdateUserProfile(1234);
   16:  
   17: }
   18: catch(exception error)
   19: {
   20: // Catch and display message. This is just an example. You 
   21: // should implement you own robust error handling.
   22: MessageBox.Show(" You do not have access to run this function")
   23: }
   24:  
   25: }
   26:  
   27:  
   28: public class myApplication
   29: {
   30:  
   31: public myApplication();
   32:  
   33:  
   34: //Step 3.
   35: [PrincipalPermission(SecurityAction.Demand, Role = @"domain\SuperUsers")]
   36: public void updateUserProfile(int empid)
   37: {
   38: --- write code here that should only be executed by specific users.
   39: }
   40:  
   41: }
   42:  
   43:  

In step3 you see that that the users in the role ="domain\SuperUsers'' only can only execute this method. If any one who is not part of this group tries to execute, the runtime will throw appropriate exception. Of course we always need to fail closed!!

In the next blog I will show how the Imperative approach can be used and then compare the advantages and disadvantages of the two schemes.