In my last post, I tried to get the following scenario to work:
One thing I didn’t add was that I’m running IIS in Windows XP, in IIS 5. In this article on CodePlex, which I originally modeled my solution after and a couple of folks pointed out, it recommends setting both the ASP.NET identity (outside the Trusted Zone) and the App Pool identity to the Service account identity.
Now, in my case, I don’t care about who calls my service, nor do I want any requirement on their side to provide any transport security. The article also recommends this, but I don’t need it.
The real problem came from me running in IIS 5. In IIS 5, the aspnet_wp process runs as MACHINEASPNET, which examining WindowsIdentity.GetCurrent() confirmed. Even though I set the identity in IIS to use the service account as anonymous user, WCF by default uses the process identity, not any other identity. WCF has no knowledge of the host environment, by default, so it doesn’t know it’s hosted in ASP.NET or IIS normally.
To do a Trusted Subsystem model under IIS 5, I had to make the following changes:
- Set the anonymous account to the service account, turn off any other security (like Integrated Windows Security)
- Turn on impersonation in the web.config (<identity impersonate=”true” />)
- Turn on ASP.NET compatibility for the service hosting environment and each individual service
The last part is critical, and detailed in this MSDN article. I’ve had to do that before, when designing JSON services for an AJAX application, where the services needed access to HttpContext.Session.
Once ASP.NET compatibility is turned on, WCF requests now go through the ASP.NET pipeline, which means the normal ASP.NET impersonation model. From the article:
WCF services run using the current identity of the ASP.NET impersonated thread, which may be different than the IIS process identity if ASP.NET impersonation has been enabled for the application.
With the full ASP.NET impersonation set up, and the correct identity set up in IIS, WCF could now take the identity of the ASP.NET impersonated thread. Even though Thread.CurrentPrincipal reflected the service identity, WCF won’t use it unless I set up the compatibility mode.
Of course, if I had been developing in a Workstation 2008 machine, or something with IIS 6 or 7, this wouldn’t be a problem. Setting the App Pool identity is the process identity. In IIS 5, the identity is configured elsewhere. In any case, it’s all working now locally. I guess this means it’s finally time to upgrade to Workstation 2008.
Thanks to everyone for all the pointers!