Monday, February 15, 2010

ASP.NET Impersonation - Part 2

This article is in continuation with my previous article "ASP.NET Impersonation - Part 1", in Part-1 I described how can we do impersonation using IIS and NTFS folder permissions. In this article I am going to explain how can we do Impersonation using custom code. The code example I am giving below is actually what I wrote long time back to authenticate my application over the network and there was a need to Impersonate users using the user credentials and I couldn't use the IIS way of impersonation.

Custom code to Impersonate application users

I have published the source code below which is a custom Impersonation class I wrote. Just copy this source code in your project as a new class and name it "cSiteImpersonation.cs" and add a reference of this class in your client project. After that is done, just call the function "ImpersonateUser(..... )" with valid credentials right before the point where you need to access the network drive/folder (where impersonation required to access the resources) and that should work.

  • Here is the definition for the function ImpersonateUser:
          ImpersonateUser(ByVal sUserName As String, _
                                        ByVal sPassword As String, _
                                        ByVal sDomain As String) 
  • Here is the source code for the Impersonation class:
/********************************************/
/****         SOURCE CODE EXAMPLE                        ****/
/********************************************/
using System;
using System.Security.Principal;
using System.Security.Permissions;
using System.Runtime.InteropServices;

namespace Sanjeev.NETArchitect.Apps.Security.AuthenticateAndAuthorize
{

    public class cSiteImpersonation
    {

        #region "Declarations"

        private enum Logon
        {
            Network = 3,
            NetworkCleartext = 8
        }

        private enum Provider
        {
            UseDefault = 0,
            WindowsNT35 = 1,
            WindowsNT40 = 2,
            Windows2000 = 3
        }

        #endregion

        #region "Public Functions"

        public WindowsImpersonationContext ImpersonateUser(string sUserName, string sPassword, string sDomain)
        {
            //-----------------------------------------
            // Function:     ImpersonateUser
            // Description:  Changes to windows identity given the input parameters.
            //
            // Inputs:       sUserName - The User to impersonate
            //               sPassword - The Password for the impersonated User.
            //               sDomain -   The Domain that is being accessed
            //
            // Outputs:      WindowsImpersonationContext, the Context for the Impersonation
             //-----------------------------------------

            WindowsIdentity objNewIdentity = default(WindowsIdentity);

            objNewIdentity = GetWindowsIdentity(sUserName, sDomain, sPassword);


            return objNewIdentity.Impersonate;
        }

        public WindowsIdentity GetCurrentIdentity()
        {
             //-----------------------------------------
            // Function:     GetCurrentIdentity
            // Description:  Returns the current windows identity.
            //
            // Inputs:       None
            //
            // Outputs:      WindowsIdentity, the current identity
            //-----------------------------------------

            return WindowsIdentity.GetCurrent();
        }

        public WindowsIdentity RevertIdentity(WindowsImpersonationContext CurrentImpersonation)
        {
             //-----------------------------------------
            // Function:     RevertIdentity
            // Description:  Undoes the impersonation, which reverts to the windows identity
            //               prior to the impersonation
            //
            // Inputs:       None
            //
            // Outputs:      WindowsIdentity, the current identity
             //-----------------------------------------

            CurrentImpersonation.Undo();
        }

        #endregion

        #region "Private Functions"

        [DllImport("advapi32.dll")]
        private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref int phToken);
        //-----------------------------------------
        // Function:     LogonUser
        // Description:  Uses the windows32 advapi32.dll to logon to the windows
        //               environment as another user.
        //
        // Inputs:       lpszUsername -      The User to impersonate
        //               lpszDomain -        The Domain that is being accessed
        //               lpszPassword -      The Password for the impersonated User
        //               dwLogonType -       Logon type
        //               dwLogonProvider -   The type of windows provider
        //               phToken -           Returned Security Token
        //
        // Outputs:      Boolean, Success or Failure
         //-----------------------------------------

        [DllImport("Kernel32.dll")]
        private static extern int GetLastError();
         //-----------------------------------------
        // Function:     GetLastError
        // Description:  Used the Kernal32.dll to get the last error .
        //
        // Inputs:       None
        //
        // Outputs:      WindowsIdentity, the Context for the Impersonation
        //-----------------------------------------

        [SecurityPermissionAttribute(SecurityAction.Demand, ControlPrincipal = true, UnmanagedCode = true)]
        private static WindowsIdentity GetWindowsIdentity(string UserName, string Domain, string Password)
        {
            //-----------------------------------------
            // Function:     GetWindowsIdentity
            // Description:  Logon the user and return the windows identity given 
            //               the input parameters.
            //
            // Inputs:       sUserName - The User to impersonate
            //               sDomain -   The Domain that is being accessed
            //               sPassword - The Password for the impersonated User.
            //
            // Outputs:      WindowsIdentity, the Context for the Impersonation
            //-----------------------------------------
            int SecurityToken = 0;
            bool Success = false;

            Success = LogonUser(UserName, Domain, Password, Logon.Network, Provider.UseDefault, SecurityToken);

            if (!Success)
            {
                throw new Exception("Logon Failed. Error: " + GetLastError());
            }


            return new WindowsIdentity(new IntPtr(SecurityToken));
        }

        #endregion

    }
}
/********************************************/



No comments: