ITM .NET Utils - PrincipalScope

by Dawid Łaziński 6. April 2009 12:11

In .NET application every thread contains the information about the Principal under which it is being executed. This can be easily checked using following property CurrentThread.CurrentPrincipal of the System.Threading.Thread class.

Usually it points to an instance of the System.Security.Principal.GenericPrincipal class and its value does not change during the application lifetime.

But, what is a GenericPrincipal?

It is a class implementing a System.Security.Principal.IPrincipal interface, which is obliged to provide two functionalities.

1. Identity property holding an instance of the class implementing the System.Security.Principal.IIdentity which in turn stores the user name and authentication details.

2. IsInRole method which allows developer to check if the user belongs to a given role.

The GenericPrincipal is a custom implementation of the mentioned interface and its instance is created every time you start a new thread. Developers are of course allowed to provide their own implementation with extended functionalities.

Why would we want to manipulate the value of the CurrentPrincipal property and when it is actually used?

One of the examples is Code Access Permission verification. Every method, property, field or even class can be decorated with the System.Security.Permissions.PrincipalPermissionAttribute attribute. It allows developers to declaratively specify the permissions required to use that code member. One could for example say:

“I would like my method Withdraw of the BankLogic class to be executed only by users belonging to the Clients role.”

The C# representation of such a limitation in code would look like this:

   1: public class BankLogic
   2: {
   3:     [PrincipalPermission(SecurityAction.Demand, Role="Client")]
   4:     public void Withdraw(decimal amount)
   5:     {
   6:         
   7:     }
   8: }

Now every time the method is about to be executed, first the required permissions are verified. The principal of the current user is taken from the CurrentPrincipal property and the method IsInRole with the “Client” string parameter is executed. If the principal denies belonging to that role the false value is returned, followed by the System.Security.SecurityException being thrown.

The exception could be caught and presented in a user friendly fashion, let that be a message box saying:

“You do not have sufficient permission to perform this action.”

However we are developing our application with respect of some latest patterns implemented in the Windows Vista operating system. In Vista, when you hit an obstacle of not being authorized to perform some action, you are given a choice of executing it using different credentials. Often it happens when you try to install a new program and call your system administrator to come to your computer and enter their credentials as you don’t have sufficient permissions.

We would like to offer a similar functionality in our application. What is required is an option to switch to another principal for some period of time or, to be more specific, for some portion of code being executed. Moreover we would like to encapsulate this operation in some kind of nice and lucid code construct.

Knowing our destination let’s now find out how we get there. Let me present you a Itm.Security.PricipalScope class.

using System;
using System.Diagnostics;
using System.Security.Permissions;
using System.Security.Principal;
using System.Threading;
 
namespace Itm.Security
{
    /// <summary>
    /// Creates new Principal scope in the current thread.
    /// </summary>
    [SecurityPermission(SecurityAction.Demand, ControlPrincipal = true)]
    public sealed class PrincipalScope : IDisposable
    {
        #region Private Static Fields
        /// <summary>
        /// Current principal scope.
        /// </summary>
        [ThreadStatic]
        private static PrincipalScope head;
        #endregion
 
        #region Public Static Properties
        /// <summary>
        /// Gets the current principal scope.
        /// </summary>
        /// <value>The current principal scope.</value>
        public static PrincipalScope Current
        {
            get
            {
                return head;
            }
        }
        #endregion
 
        #region Private Static Fields
        /// <summary>
        /// Default thread principal.
        /// </summary>
        [ThreadStatic]
        private readonly IPrincipal firstPrincipal;
 
        /// <summary>
        /// Indicates if the scope has been disposed.
        /// </summary>
        private bool isDisposed;
 
        /// <summary>
        /// Current scope parent scope.
        /// </summary>
        private readonly PrincipalScope parent;
 
 
        /// <summary>
        /// Current scope principal.
        /// </summary>
        private readonly IPrincipal principal;
        #endregion
 
        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="PrincipalScope"/> class.
        /// </summary>
        /// <param name="principal">The principal to be used in this scope.</param>
        public PrincipalScope(IPrincipal principal)
        {
            if (principal == null)
            {
                throw new ArgumentNullException("principal");
            }
 
            this.principal = principal;
 
            if (head == null)
            {
                firstPrincipal = Thread.CurrentPrincipal;
            }
 
            parent = head;
            head = this;
 
            Thread.CurrentPrincipal = principal;
        }
        #endregion
 
        #region IDisposable Members
        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            if (isDisposed)
            {
                return;
            }
 
            isDisposed = true;
 
            Debug.Assert(this == head, "Disposed out of order.");
 
            head = parent;
 
            Thread.CurrentPrincipal = head == null ? firstPrincipal : head.principal;
        }
        #endregion
    }
}

The class has a few important bits I will explain right now.

First is declares only two public entry points visible to the developer. The constructor and the Current static property.

The constructor is used to create new instance of the class therefore declaring a new principal scope. Once the constructor is called the value of the CurrentPrincipal property of the current thread is altered and now points to the principal passed as an argument to the constructor. The change of the scope is also reflected by the Current static property of the PrincipalScope class. Now if we call the constructor again, another principal is going to be set as the current one.

The value of the Current property comes from the head field which is decorated with System.ThreadStaticAttribute attribute. This attribute tells CLR that the field may have different values in different threads. The default behavior is that static fields share the same value among all threads in the same AppDomain. Our solution ensures that new scopes are created only in the specific thread. Otherwise we would accidently alter the principals of the other threads.

By now we know only how to create new scopes. But how do we force the existing scope to end?

You may have already noticed that our class implements the System.IDisposable interface. This means that we can call Dispose method on it, and this is exactly where the scope is being forced to end.

Every scope also holds a reference to the scope it is replacing, stored in the parent field of each instance. This allows us to set the CurrentPrincipal property on the thread back to its previous value when the Dispose method is called, nicely cleaning all the changes we had made.

IDisposable interface serves not only as a way of terminating the scope. We could achieve the same result using some dedicated method like Terminate or Finish. However C# offers a special code construct to handle classes implementing IDisposable interface.

You may already be familiar with the using keyword. For those who are not, let me briefly present you its purpose.

using keyword takes an instance of the IDispoable interface and opens a new block of code. Once the block ends it automatically calls the Dispose method on that instance. Moreover it catches any exception throw within the block. If that happens the Dispose method is called and the exception is rethrown.

This allows us to use the PrincipalScope class in a very neat way:

   1: using (new PrincipalScope(ourPrincipalInstance))
   2: {
   3:     BankLogic logic = new BankLogic();
   4:  
   5:     logic.Withdraw(1000);
   6: }

Let’s imagine we are logged on to the banking system using our everyday account. Now we want to perform a withdrawal on a different account, however we don’t belong to the Clients role, therefore have insufficient permissions. We may temporally log on as a different person creating a new instance of the IPrincipal class, now stored in the ourPrincipalInstance variable.

All we need to do now is to create a new principal scope using that variable (line 1), perform the withdrawal (lines 3-5) and terminate the scope (line 6).

Implementing IPrincipal and user authentication and authorization process is beyond the scope of this article and varies in every application.

I hope you will find PrincipalScope useful and decide to use it in your own applications. You may extend its functionalities by adding some change notification and other properties. If you have any comments feel free to post them below or contact me directly on my e-mail.

I don’t include any code files as the entire implementation is available in the code block in the middle of the article.

Currently rated 5.0 by 4 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

.NET

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen