« Back
in C# .NET SimpleImpersonation Impersonation read.

Windows Impersonation in an MVC Application.

Preamble

A very simple way of doing Windows impersonation is using a neat little nuget package called SimpleImpersonation by Matt Johnson. Generally you would use impersonation when you want to access resources on a networked machine or perform some action with elevated privileges.

I'd like to discuss on how to use SimpleImpersonation and then refactor the code to make it a little less repetitive when you need to execute functions under impersonation throughout your project.

Install SimpleImpersonation

In your package manager console for your MVC Application issue the following command:
Install-Package SimpleImpersonation

Using SimpleImpersonation

As per the GitHub page, we can use SimpleImpersonation in this way:

using (Impersonation.LogonUser(domain, username, password, logonType))  
{
    // do whatever you want as this user.
}

Of course we don't want to directly put in our domain, username and password into the code so we're going to have to pull it from somewhere like the webconfig. Then it would look something like this:

using (Impersonation.LogonUser(  
System.Configuration.ConfigurationManager.AppSettings["ImpersonationDomain"],  
System.Configuration.ConfigurationManager.AppSettings["ImpersonationUser"],  
System.Configuration.ConfigurationManager.AppSettings["ImpersonationPassword"],  
LogonType.Interactive))  
{
    // do whatever you want as this user.
}

However if we use this in multiple areas, it starts getting tedious. So let's refactor this a bit and move it to its own helper class.

Refactoring the Impersonation

using SimpleImpersonation;  
using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;

namespace AppNamespace.HelperClasses  
{
    public class WindowsImpersonation
    {
        private readonly static string _username = System.Configuration.ConfigurationManager.AppSettings["ImpersonationUser"];
        private readonly static string _password = System.Configuration.ConfigurationManager.AppSettings["ImpersonationPassword"];
        private readonly static string _domain = System.Configuration.ConfigurationManager.AppSettings["ImpersonationDomain"];

        protected WindowsImpersonation() { }

        public static T ExecuteFunction<T>(Func<T> function)
        {
            T result;
            if (!System.Diagnostics.Debugger.IsAttached)
            {
                using (Impersonation.LogonUser(_domain, _username, _password, LogonType.Interactive))
                {
                    result = function();
                }
            }
            else
            {
                result = function();
            }

            return result;
        }
    }
}

So let's take a look at what happened here. First we made it a static class so that it can be called anywhere without an instantiation. Then I put all the login details into private variables. That way we don't have to specify it every time.

In this instance, ExecuteFunction<T> and (Func{<T>}) will allow a return type of T. This allows us to execute the function we want inside the impersonation routine and return type T. Additionally we checked to see if the debugger was attached e.g. running inside Visual Studio. If it is, we'll skip the impersonation.

Using The New WindowsImpersonation Class

Now every time we want to execute something using impersonation we simply call it like this:

    WindowsImpersonation.ExecuteFunction<bool>(() =>
    {
       //Do stuff
       return true;
    });
comments powered by Disqus