I hope you can help me.
I am doing some webrequests within my C# 4.0 application which require authentication. I simply use the CredentialsCache.DefaultCredentials
. This works great as long as I do not run the functionality in a different thread / task via Task<T>.Factory.StartNew(...)
. I then get 401 errors. I assume that the credentials are not passed through to child threads?
How can I pass through the credentials to any child tasks / threads?
I assume that you are using impersonation and that the problem is that the credentials are not being flowed into the Task. It's worth checking this point to save a wild goose chase by dumping out the value of
Windows.Identity.GetCurrent().Name
in both the initiating code and the Task body and making sure it's what you expect.So given the above, there are a couple of ways that (to put it formally) execution context (or just security context) is not being flowed across threads. The default behaviour is that context is flowed - so something must be affecting that.
1) Something has set
ExecutionContext.SuppressFlow()
- you can check this by dumping the value ofExecutionContext.IsFlowSuppressed()
inside the task.2) There is a configuration element
<legacyImpersonationPolicy>
(conifguration->runtime->legacyImpersonationPolicy) that defaults tofalse
. Whenfalse
, WindowsIdentity is flowed across asychronous points. Whentrue
it is not. This is regardless of the ExecutionContext flow settings. Sotrue
here would cause a problem for you. You can check this by dumping the value ofSecurityContext.IsWindowsIdentityFlowSuppressed()
is your task. This can also be programmatically set per thread withSecurityContext.SuppressFlowWindowsIdentity()
.Finally, for completeness, in case you are using unmanaged code there is another setting
<alwaysFlowImpersonationPolicy>
that controls how impersonated credentials are flowed in unmanaged scenarios as well; the other settings described only affect managed code.