views:

270

answers:

4

I have a method that attempts to update a sql server database in an ASP.NET application. If the update fails, it catches the exception and then queues the update in MSMQ, and then spins up a new thread that will later de-queue the pending update and try again. When the thread starts, it fails to open a database connection because it is attempting to connect using Network Service as the login. The sql connection is using Windows Authentication, and will work outside of the thread. If I put a breakpoint in the code that executes inside the new thread and check the Thread.CurrentPrincipal, it shows the Identity as being the correct user. Why is the sql connection attempting to be opened by the Network Service account?

I can elaborate further is necessary.

Thanks.

+1  A: 

I think you need to check the identity of the application pool the website is running under in IIS - is it set to Network Service?

Also, what impersonation setting is in your web.config file? Check if you are impersonating the current user, a specific user, or no user (and the application pool identity is therefore being used).

It would be useful if you posted your connection string too.

Owen Orwell
The app pool is using the default Network Service identity.In the web.config, the identity has impersonate="true", and we are impersonating a specific account.The connection string is using Trusted_Connection=yes;data source=myDataSource;I found this article: http://support.microsoft.com/kb/326606 which might be similar. I am not using Session State, but this article indicates that session state uses a background thread to connect to the sql server database, and therefore cannot connect because the thread runs under the ASP.NET worker process.
Jonathan M
+1  A: 

I figured it out based on this thread: http://bytes.com/topic/asp-net/answers/597465-simple-thread-issue

I had to add this to the top of the thread's code block:

((WindowsIdentity)Thread.CurrentPrincipal.Identity).Impersonate();
Jonathan M
Actually, this will not work either, since I checked what credentials the database was using to make the calls from the Main thread and the Background thread. It turns out the above was just impersonating me (the logged in user), and not the service account specified in the web.config. Since I had access to the database, the call was successful, but when this goes to production, this won't be the case. o now I am looking at ExecutionContext and seeing if that buys me something..
Jonathan M
A: 

This link is where I found the answer: http://www.leastprivilege.com/WhatIsAspnetconfig.aspx

Here is the key bit of info:

<configuration>
  <runtime>
    <legacyUnhandledExceptionPolicy enabled="false" />
    <SymbolReadingPolicy enabled="1" />

    <legacyImpersonationPolicy enabled="false" />
    <alwaysFlowImpersonationPolicy enabled="true" />
  </runtime>
<configuration>
Jonathan M
+1  A: 

I have discovered an even more elegant solution that does not require the modifications to the aspnet.config file.

// get the current WindowIdentity of the main thread
var currentIdentity = WindowsIdentity.GetCurrent();

Thread thread;
thread = new Thread(() =>
            {
                // using lambda closure, access the current identity
                // inside the background thread scope and call Impersonate
                var context = currentIdentity.Impersonate();

                // do multi-threaded stuff


                // undo the impersonation before leaving the thread
                context.Undo();
            })
        {
            Name = "BackgroundThread",
            IsBackground = true
        };
thread.Start();
Jonathan M