.NET Identity and Principal Objects Part 3: Identity Flow and Impersonation Across Process and Machine Boundaries
The first and second articles in this series covered the basics of .NET identity based security and showed you how to implement custom authentication and authorization schemes. In this last installment, we examine the issues related to identity flow and identity impersonation across.NET-distributed multilayered applications.
Identity Flow
As explained in the first article of this series, the .NET Framework keeps identity- and role-related information in the running thread's CurrentPrincipal property. Once this property has been set, typically during the authentication phase, the .NET Framework propagates it along the thread's execution flow and uses it to perform access checks when required. However, a modern application often consists of different pieces of software distributed on more than one machine following the classic three-tiered distributed application pattern (Presentation tier, Business tier, Data tier).
In this situation, the logical thread of execution accomplishing a given application task may spawn across different processes and computer boundaries. Evidently, one needs mostly to have the caller identity flow across process and machine, so that a server executing some work on behalf of the client will do it under the caller identity.
Although this is possible in .NET, unfortunately the way you do it varies with the technology used for remote objects/services invocation: ASP.NET/Web Services, .NET Remoting, and DCOM.
Regarding identity flow, the WindowsIdentity object deserves special consideration. It can't be serialized because it points to Windows' private, process-specific data structures. As a consequence, you must obey Windows rules to transport a valid WindowsIdentity object from the client to the server (more on this later).
Once you manage to transfer the caller identity to the server, you have two options:
Simply attach the WindowsIdentity to the thread's CurrentPrincipal to execute only .NET-specific access checks. However, in this case, Windows will continue to use the server process identity when the resources that the OS is aware of are accessed.
Switch to the caller identity at the Windows level as well, so that even OS-protected resources will be access-checked using the client identity. This is called impersonation.
When you avoid impersonation, you basically state that the application will take care of access checks without delegating them to the OS or downstream services such as databases. In this case, you typically configure the server processes (application servers, Web servers) so they are granted the super set of permissions (OS, file ACL, database permissions) required by the application to execute the whole of its functionalities.