OK, you found the geek stuff, all related to Microsoft or dotNet. That is, as I have worked with Microsoft since their early days and with dotNet since its betas.

Identities in Web Services
Working with multi-tier applications it always has been important to know under which account specific services are running. Probably the most common approach is to let clients running the User Interface connect to a service that on its term connects to the database. To protect against unauthorized access of data only the privileged account that the service is running under is permitted to connect to the database.

That said let’s take a look at Web Services and ask the question: What is the effect of authentication and impersonation settings within Internet Information Server?

Anonymous web services run under the account of the web site and have no further knowledge of the identity of the caller. You will see that the System.Security.Principal.WindowsIdentity is set to the account defined in IIS. That is by default a local account IUSR_>machinename<. All threads spawned to handle incoming web service requests have the same principal, having the same 'anonymous' identity. This can be checked looking at the System.Threading.Thread.CurrentPrincipal.Identity property.

Once you clear the 'anonymous' flag the caller will be requested to provide its credentials. Within the client proxy code you will find code like this:
_service.Credentials = System.Net.CredentialCache.DefaultCredentials;
Interesting is to observe what happens on the Web Service side: the WindowsIdentity remains the IIS account, but the ‘thread identity’ is set to the account under which the client runs. It is the thread’s principal, not the WindowsIdentity of the process, that is used to apply the dotNet authorization for methods using the System.Security.Permissions.PrincipalPermission attribute.

Setting the impersonation flag to true causes IIS for a much heavier operation. It now will set the WindowsIdentity of the thread based on the client’s credentials. Consequently threads will run under different WindowsIdentities for different users, such that for example connection pools cannot be used. As authorization just needs the ‘thread identity’ based on a principle it is mainly due to the performance consequences that impersonation is depreciated. Note that for security reasons one can only impersonate using a ‘token’. This token is either retrieved by logging onto the system (using username and password), or by a secure 'channel'. Such a channel is provided with HTTP using "Integrated Windows Authorization".

What does this mean for the scenario given above? If you use a Web Service to communicate between client and server and clear the anonymous option, the thread’s principal that is instantiated which is sufficient to secure the services offered as outlined above. And throughout the service is the identity of the caller known, e.g. to keep track of who modified the database content. This similarly holds if you use dotNet remoting.

But how does this come into play if you use the Web Service from within your server application? In that case the identity passed is based on the server application’s identity. It are its credentials that are used for authentication of the Web Service. The ‘thread identity’ on the Web Service is thus the account the server process uses, not the user’s account of the request. The real user identity is not passed, if one would like to forward it, it needs to be done in a custom manner, for example setting additional custom SOAP headers. I believe that this is from a security point of view no problem. The Web Service is called on behalf of the privileged service, it’s an extension of that service. If the user is not allowed for the Web Service operation the service should guard this. In fact, you may not even wish that the Web Service takes the users identity into account to exclude specific data, e.g. as the data is aggregated before it is sent to the user. But what remains to be a challenge is tracking. With the users identity gone yet another piece of information to relate calls over process boundaries is gone.

Impersonation in the server process would allow for the Web Service called by that server process to know about the user’s identity. Note, this is clearly not recommended and requires additional configuration to allow for what is called delegation. And if you use dotNet remoting between client and server you will notice that impersonation of the remoting service is not supported. That is as dotNet 1.1 remoting does not support a secure channel to transfer the necessary user token.

One other aspect of identity is of interest to be shared. As outlined above, Web Services will run by default under the local account IUSR_<machinename>. If you are accessing a database as third tier, this can cause you some problems. Generally this account will have no rights to access any data from your database. Of course, you could grant permissions to the NT_AUTHORITY\NETWORK SERVICE account, but that will only work for you as a developer. Once the database is placed onto a separate machine you are in trouble with the local account. Therefore configure for your application a dedicated application pool within IIS that is using a domain account. This also allows for a much easier load balancing configuration once you want to spawn your Web Service over multiple servers.

A lot more background information can be found for example in http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetch10.asp. All I want you to take with you is that impersonation in most cases in not necessary. It is depreciated because of its impact for scalability and the larger administration efforts. And Web Services that access a database should be running in a dedicated application pool that uses a domain account.

Posted September 2006
C#, dates and Web Services
Co-authoring a book on SharePoint Portal Server 2001
Published articles