WCF Service user impersonation options in IIS7.0 +
October 03, 2011
I recently had a problem where I wanted my WCF services to run under the context of a user with additional permissions over the standard ApplicationPoolIdentity
user used when hosting WCF services under IIS, including opening named pipe clients. I got a little burnt, and thought I’d share a couple of options I explored.
ASP.net impersonation
Though WCF has been designed to be transport-independant, you can utilise ASP.net compatibility mode, which gives you the opportunity to get your services to impersonate as a given user through standard ASP.net means, by adding the following to your web.config
:
<system.web><identity impersonate="true"/></system.web>
This will cause your services to impersonate the current user. See http://msdn.microsoft.com/en-us/library/ff647404.aspx under the section ‘To impersonate the original caller’, which does a great job of explaining this.
Then, if you want ALL your WCF service requests to run under the identity of a pre-defined user, the identity element further supports the username and password attributes, e.g.
<system.web><identity impersonate="true" username="user" password="pass" /></system.web>
Where user is a local or domain user. The above will give you access to the resources that user is capable of accessing.
If you want to take advantage of this for your WCF services, you should configure your services as follows:
1. In your web.config, set the aspNetCompatibilityEnabled
attribute to true on the system.serviceModel
element:
<system.serviceModel>...<serviceHostingEnvironment ... aspNetCompatibilityEnabled="true"/></system.serviceModel>
2. On your service implementation (the class that implements your service contract), set the AspNetCompatibilityRequirementsMode
attribute at the class level.
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Required)]public class Service : IService {public bool DoSomeWorkThatRequiresElevatedPermissions(int id)}
The AspNetCompatibilityRequirementsMode
attribute will ensure that the service instantiation fails if the aspNetCompatibilityEnabled
attribute has not been added to the web.config.
This should be enough to get the service to run as the impersonated user you set in the web.config, and on the surface it seemed to give me the appropriate behaviour, with the WCF services able to access folders I had secured for access only by a given user - until I began using the Task Parallel Library (TPL) from within the service operations to spin off some long running operations in seperate threads. TPL provides a nice clean API to spin off threads as Task
’s, but it seemed the running of the service in the context of the impersonated user in the web.config did not extend to any threads spun off by the service.
Run WCF service as…
In order to enable WCF services to run as a specific user, I thought of extracting the services that required elevated permissions and have them run as a windows service. Or instead, with the services being hosted under IIS, run the services under a separate application pool and set this application pool’s identity to the user with the permissions to access the required resources. This solved my problem - any threads spun out as part of the service ran under the context of the new application pool identity, meaning you can use all the loveliness of the TPL.
To take advantage of this, head to the Internet Information Services (IIS) Manager. I’m using Windows 7 64-bit, which comes with IIS 7 by default, but most of these instructions should apply to earlier versions also, though the location of the settings panels will be different.
Select ‘Application Pools’ over in the left hand bar of the IIS Manager and create an app pool relevant for your WCF services (.NET 4.0/Integrated pipeline should do). Here, I’m going to call mine ElevatedAppPool.
Once you’ve created it, select it and click ‘Advanced Settings’ in the Actions pane on the right hand side of the IIS Manager. Under Process Model you should see an ‘Identity’ element, which if you click … you can assign a custom account to it. This can be either a domain or local machine account.
Finally, go back to the application that your WCF services are located by expanding the Sites tab on the left hand side of the IIS Manager. Click ‘Advanced Settings’ and select the application pool you just set up. You should now find your WCF services are running under this user with elevated permissions.
You could of course, have given the ApplicationPoolIdentity
the extra permissions (such as reading or writing to a particular folder outside wwwroot) but having a seperate identity/application pool makes the changes specific to this set of WCF services, and not for other application pools that may be using the ApplicationPoolIdentity
user.