Set Identity of Thread
Asked Answered
O

3

28

In C#, how do I set the Identity of a Thread?

For example, if I have Thread MyThread, which is already started, can I change MyThread's Identity?

Or is this not possible?

Orebro answered 3/11, 2008 at 14:49 Comment(0)
D
34

You can set the Identity of a thread by creating a new Principal. You can use any Identity that inherits from System.Security.Principal.IIdentity, but you need a class that inherits from System.Security.Principal.IPrincipal that takes the type of Identity you are using.
For simplicity sake the .Net framework provides GenericPrincipal and GenericIdentity classes which can be used like this:

 using System.Security.Principal;

 // ...
 GenericIdentity identity = new GenericIdentity("M.Brown");
 identity.IsAuthenticated = true;

 // ...
 System.Threading.Thread.CurrentPrincipal =
    new GenericPrincipal(
        identity,
        new string[] { "Role1", "Role2" }
    );

 //...
 if (!System.Threading.Thread.CurrentPrincipal.IsInRole("Role1"))
 {
      Console.WriteLine("Permission denied");
      return;
 }

This won't however give you windows rights to stuff using the new identity. But it can be useful if you are developing a web site and want to create your own user management.

If you want to pretend to be a different Windows user than the account you are currently using then you need to use impersonation. An example of how to do this can be found in the Help for System.Security.Principal.WindowsIdentity.Impersonate(). There are limitations about which accounts the account you are running under can impersonate.

In some cases the .Net framework does impersonation for you. One example of where this occurs is if you are developing a ASP.Net web site and you have Integrated Windows Authentication switched on for the virtual directory or site you are running in.

Debra answered 3/11, 2008 at 16:28 Comment(4)
If you use GenericIdentity Constructor (String, String) you can skip the IsAuthenticated = true bit.Asphaltite
I am using .NET 4.5, and i can not compile this statement identity.IsAuthenticated = true; because the property "IsAuthenticated" has only get accessor, can you please, make an update for the code in which the case of using .NET 4.5 framework. thank you any way, your code was helped me, (with some modifications)Coelenterate
I modified your code in .NET 4.5 as the following to make it work GenericIdentity identity = new GenericIdentity("user1", "Forms"); Thread.CurrentPrincipal = new GenericPrincipal(identity, new string[] { "role1" }); you could use this code to update you helpful post, thank you again.Coelenterate
Will this work with Windows Authe enabled and Forms Auth enabled in IIS website?Killerdiller
A
4

Update for the accepted answer [apply ONLY on .NET framework 4.5 and above]
In .NET 4.5 the property IsAuthenticated has no set accessor, so you can not set it directly as the accepted answer doing.
You can use the following code for setting that property.

GenericIdentity identity = new GenericIdentity("someuser", "Forms");
Thread.CurrentPrincipal = new GenericPrincipal(identity, new string[] { "somerole" });
Adulterant answered 22/8, 2015 at 14:0 Comment(2)
Will this work with Windows Authe enabled and Forms Auth enabled in IIS website?Killerdiller
Hypothetically, Yes it should, because at the end this is the new syntax you should use if you are using the 4.5 .NET framework and above.Coelenterate
W
3

Yes, using impersonation literally

using (new Impersonation())
{
    // your elevated code
}

and the class is as follows, for settings I use castle dictionary adaptor if it looks strange.

[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public class Impersonation : IDisposable
{
    private readonly SafeTokenHandle _handle;
    private readonly WindowsImpersonationContext _context;

    //const int Logon32LogonNewCredentials = 9; 
    private const int Logon32LogonInteractive = 2;

    public Impersonation()
    {
        var settings = Settings.Instance.Whatever;
        var domain = settings.Domain;
        var username = settings.User;
        var password = settings.Password;
        var ok = LogonUser(username, domain, password, Logon32LogonInteractive, 0, out _handle);
        if (!ok)
        {
            var errorCode = Marshal.GetLastWin32Error();
            throw new ApplicationException(string.Format("Could not impersonate the elevated user.  LogonUser returned error code {0}.", errorCode));
        }
        _context = WindowsIdentity.Impersonate(_handle.DangerousGetHandle());
    }

    public void Dispose()
    {
        _context.Dispose();
        _handle.Dispose();
    }

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

    public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        private SafeTokenHandle()
            : base(true)
        { }

        [DllImport("kernel32.dll")]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr handle);

        protected override bool ReleaseHandle()
        {
            return CloseHandle(handle);
        }
    }
}
Wordsworth answered 3/11, 2008 at 14:53 Comment(3)
Can you elaborate? If MyThread was already running, can we change it's CurrentPrincipal?Orebro
Surprisingly this link helped me in solving my issue. While it's not setting the Thread identity, it allows you to run code whilst impersonating another user. By examining the first example in the link I made a copy of the current user identity in my main thread using: var newId = WindowsIdentity.GetCurrent(); Afterwards I passed this identity to my threads and impersonated the user with this clause: using (var impersonationContext = newId.Impersonate()) Code executed inside the using will run under the Impersonated identity.Inspirational
@Paul indeed it has proven useful to myself as well, think I'll update the answer as it is a little light in retrospectWordsworth

© 2022 - 2024 — McMap. All rights reserved.