WindowsImpersonationContext & Impersonate() not found in ASP.Core
Asked Answered
F

2

24

I had the following in a .NET Framework 4.0 assembly:

var newId = new WindowsIdentity(duplicateTokenHandle);
WindowsImpersonationContext newId = ImpersonatedIdentity.Impersonate();

I'm porting it to ASP.Core, but WindowsImpersonationContext and WindowsIdentity.Impersonate() aren't found.

I've tried adding the following:

Type Version
System.Security.Claims 4.3.0
System.Security.Principal 4.3.0
System.Security.Principal.Windows 4.3.0

How do I perform impersonation in ASP.Core?

Update

It looks like it's not supported in .NET Core or .NET Standard - is there a work-around or do I have to resign to targeting the framework?

Fascicle answered 2/10, 2017 at 15:52 Comment(1)
There's a new method called RunImpersonated.Shoreless
V
22

Necromancing.

Like this:

using System.Security.Principal;


namespace regeditor
{


    public class WindowsLogin : System.IDisposable
    {
        protected const int LOGON32_PROVIDER_DEFAULT = 0;
        protected const int LOGON32_LOGON_INTERACTIVE = 2;

        public WindowsIdentity Identity = null;
        private System.IntPtr m_accessToken;


        [System.Runtime.InteropServices.DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool LogonUser(string lpszUsername, string lpszDomain,
        string lpszPassword, int dwLogonType, int dwLogonProvider, ref System.IntPtr phToken);

        [System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        private extern static bool CloseHandle(System.IntPtr handle);


        // AccessToken ==> this.Identity.AccessToken
        //public Microsoft.Win32.SafeHandles.SafeAccessTokenHandle AT
        //{
        //    get
        //    {
        //        var at = new Microsoft.Win32.SafeHandles.SafeAccessTokenHandle(this.m_accessToken);
        //        return at;
        //    }
        //}


        public WindowsLogin()
        {
            this.Identity = WindowsIdentity.GetCurrent();
        }


        public WindowsLogin(string username, string domain, string password)
        {
            Login(username, domain, password);
        }


        public void Login(string username, string domain, string password)
        {
            if (this.Identity != null)
            {
                this.Identity.Dispose();
                this.Identity = null;
            }


            try
            {
                this.m_accessToken = new System.IntPtr(0);
                Logout();

                this.m_accessToken = System.IntPtr.Zero;
                bool logonSuccessfull = LogonUser(
                   username,
                   domain,
                   password,
                   LOGON32_LOGON_INTERACTIVE,
                   LOGON32_PROVIDER_DEFAULT,
                   ref this.m_accessToken);

                if (!logonSuccessfull)
                {
                    int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
                    throw new System.ComponentModel.Win32Exception(error);
                }
                Identity = new WindowsIdentity(this.m_accessToken);
            }
            catch
            {
                throw;
            }

        } // End Sub Login 


        public void Logout()
        {
            if (this.m_accessToken != System.IntPtr.Zero)
                CloseHandle(m_accessToken);

            this.m_accessToken = System.IntPtr.Zero;

            if (this.Identity != null)
            {
                this.Identity.Dispose();
                this.Identity = null;
            }

        } // End Sub Logout 


        void System.IDisposable.Dispose()
        {
            Logout();
        } // End Sub Dispose 


    } // End Class WindowsLogin 


} // End Namespace 

Usage:

// WindowsIdentity user = (WindowsIdentity)context.User.Identity;
// using (WindowsIdentity user = WindowsIdentity.GetCurrent())

using (WindowsLogin wi = new WindowsLogin("Administrator", System.Environment.MachineName, "TOP_SECRET"))
{
    #if NET461
    using (user.Impersonate())
    #else
    WindowsIdentity.RunImpersonated(wi.Identity.AccessToken, () =>
    #endif
    {
        WindowsIdentity useri = WindowsIdentity.GetCurrent();
        System.Console.WriteLine(useri.Name);
    }
    #if !NET461
    );
    #endif
    
}*
Valeryvalerye answered 11/8, 2018 at 12:5 Comment(1)
I had to change the logon type to LOGON32_LOGON_NETWORK_CLEARTEXT, but otherwise, this worked like a charm! Thanks.Honkytonk
F
9

As @Tratcher mentioned you can use the RunImpersonated in .netstandard. The following code sniped is taken from here.

    var user = (WindowsIdentity)context.User.Identity;
#if NET461
    using (user.Impersonate())
#else
    WindowsIdentity.RunImpersonated(user.AccessToken, () =>
#endif
    {
        // var useri = WindowsIdentity.GetCurrent();
    }
#if !NET461
    );
#endif
Fiddlehead answered 3/10, 2017 at 8:57 Comment(4)
Works in .Net Core 2.0Hospers
And where do you get the context?Skidmore
@PatrickSzalapski It's the IHttpContext. I think you can use dependecy injection in asp.net core to get it.Fiddlehead
There's no way to get a WindowsIdentity from the HttpContext in .NET Core as far as I can tell--it looks like you'd need to use native calls to query Active Directory, and for that you have to know the user's password.Skidmore

© 2022 - 2024 — McMap. All rights reserved.