Nielsen's Weblog : .NET [use your Context dude]
Updated: 14-04-2006; 19:23:41.

 

Subscribe to "Nielsen's Weblog" in Radio UserLand.

Click to see the XML version of this web page.

Click here to send an email to the editor of this weblog.

 
 

23. marts 2006

Apparently in .NET 2.0 the impersonation token is propagated across threads, this was not the case in 1.1.

In .NET 2.0 you can perform the following code in a simple console app:

class GoWithTheFlow
{
 public static void IdentityMatters(object state)
 {
  Console.WriteLine("Thread Identity " +WindowsIdentity.GetCurrent().Name);
 }
  
 static void Main()
 {
  Console.WriteLine("User before impersonation : " + WindowsIdentity.GetCurrent().Name);
  ImpersonateUser x = new ImpersonateUser();
  x.Impersonate();
  Console.WriteLine("In Main, my identity : " + WindowsIdentity.GetCurrent().Name);
  ThreadPool.QueueUserWorkItem(new WaitCallback(IdentityMatters), 42);
  Thread.Sleep(1000);
  Console.WriteLine("back In Main, my identity: " +WindowsIdentity.GetCurrent().Name);
  x.Undo();
  Console.WriteLine("After undo In Main, my identity: " +WindowsIdentity.GetCurrent().Name);
  Console.Read();
 }
}

Assuming the ImpersonateUser will do the usual LogonUser thing, in my case with the account Kill Bill on server NEO. The output is show here:

User before impersonation : NEO\Allan
In Main, my identity : NEO\Kill Bill
Thread Identity : NEO\Kill Bill <--good stuff
back In Main, my identity: NEO\Kill Bill
After undo In Main, my identity: NEO\Allan

As you can see the impersonation token it actually propagated across the thread. In .NET 1.1 the output would be

User before impersonation : NEO\Allan
In Main, my identity : NEO\Kill Bill
Thread Identity : NEO\Allan <--bad thing
back In Main, my identity: NEO\Kill Bill
After undo In Main, my identity: NEO\Allan

This is of course great news, but here is my observation in regards to trying to achieve the same thing in a webservice. To quickly test this, create an asmx endpoint with the following code in it:

[WebService(Namespace = "http://identityflow.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
    public Service (){}
    static AutoResetEvent are;
    static bool complete = false;
    [WebMethod]
    public string IdentityMatters()
    {
        this.Context.Trace.Write("Current Identity before thread : " + WindowsIdentity.GetCurrent().Name);
        are = new AutoResetEvent(false);
       ThreadPool.QueueUserWorkItem(new WaitCallback(YourIdentityPlease), this);
        if (!complete)
            are.WaitOne();
        this.Context.Trace.Write("back in business, Identity:  " + WindowsIdentity.GetCurrent().Name);
        return "done";
    }
    public static void YourIdentityPlease(object state)
    {
        Service s = (Service)state;
        s.Context.Trace.Write("thread Identity: " + WindowsIdentity.GetCurrent().Name);
        complete = true;
        are.Set();
    }
}

In your web.config turn on the <identity impersonate="true"/>

Under IIS, turn off the 'Anonymous access' and check the 'Integrated Windows authentication'.

when you activate the endpoint, the output in tracelog shows this :

: Current Identity before thread : NEO\Allan
: thread Identity : NEO\ASPNET <-- did not expect this
: back in business, Identity:  NEO\Allan

Hmm ... the impersonation token is NOT propagated !!!

"Never send a human to do a machine's job"
 -- Agent Smith.

[update]

thanks for sharing this.

apparently this behaviour is for legacy reasons. You need to modify the aspnet.config file located in your runtime directory \WINDOWS\Microsoft.NET\Framework\v2.0.50727

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <runtime>
        <legacyUnhandledExceptionPolicy enabled="false" />
        <legacyImpersonationPolicy enabled="true"/>
        <alwaysFlowImpersonationPolicy enabled="true"/>
        <SymbolReadingPolicy enabled="1" />
    </runtime>
</configuration>

some documentation on this can be found here

sticking this information in the config file doesn't help, inetinfo's job is to locate the endpoint and then load the correct isapi, and as usual it's aspnet_isapi.dll and that isapi extention needs this information before the AppDomain is created in the aspnet_wp.exe.

"The greatest mistake a man can make is to be afraid of making one."
  --Elbert Hubbard


11:47:40 AM    comment []

© Copyright 2006 Allan Nielsen.



Click here to visit the Radio UserLand website.
 


March 2006
Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
Dec   Apr