Impersonation and Delegation - There is too much confusion!
Let’s start by impersonation. The dictionary meaning of the word goes something like – “to assume or act the character of” or “pretend to be”. The easiest way I can explain this to compare this with mimicry artists. When they mimic someone else’s way of talking, walking, dressing etc, they are pretty much impersonating that person. If the mimicry artist is good, he/she can pretty much pass on as the real person. In software terms, the general meaning remains the same. Since we are really going to “pretend” to be someone, we should be able to authenticate on that person’s behalf and hence ID and password are required to be able to impersonate.
The idea of impersonation is essentially to assume identity of a particular person when accessing resources on a thread. The resources could be files, event log, data base etc, but pretty much on the local machine and these resources typically need to be protected by appropriate ACLs (access control list), else impersonation has no real significance. Here also note that “thread” is important. All code execution essentially happens on some thread and it is this threads identity that we are addressing. Threads typically inherit the process identity and hence will access all local resources using that identity. In case you want to access the resources using some other identity, you need to resort to impersonation. By doing impersonation, you can either increase or decrease your access rights on the resources.
Who do you impersonate? This really depends on the needs and also on the type of application. In windows (thick client) application, the process and threads run under the identity of the person logged onto the machine, so they are essentially impersonating the logged in user. All local machine resource access is done by using that identity and since most of us are administrators on local machines, we are able to access all resources without any security issues. This typically is the cause of “works on local machine but fails on remote machine” type of issues. In most thick client applications, we don’t have a need to impersonate, though theoretically we can.
In case of windows service, the process runs under the identity configured for that service and hence in turn the threads run in the same context. This is usually the “log on as” setting for the services and by and large most services run under “local system” account. Now this account is again a high privilege account and typically has full rights on the local system. If you change the “log on as” identity, you are essentially setting which identity the service should impersonate when accessing resources.
Finally let’s look at ASP.NET and this is typically where things become a bit more complex. By default the ASP.NET process runs using ASPNET (if on IIS 5) or NETWORK SERVICE (if on IIS 6 onwards) identity. All local resource access is done using this identity. Typical issues like can’t create a new event log via a web application or can’t access file is due to this, since the default identities don’t have these privileges on the local system. Multiple ways exist for impersonation
1. Impersonate the logged in user. Note that this really has meaning if you are using Windows or forms authentication. If you have set your site to “Anonymous”, then impersonating logged in use has no real meaning.
2. Impersonate a specific user by providing the ID and password in web.config
3. Impersonate a specific user by setting it as process identity. In IIS 6 onwards, this means setting the identity of the application pool within which the asp.net application is running.
4. Localized impersonation in code. You can create an impersonation context in code, invoke some APIs and then return to original thread identity
Options 1 and 3 are the more often used approaches. If you want to know how to put this in practice in ASP.NET, c heck this support article - http://support.microsoft.com/kb/306158.
In summary, impersonation is pretending to be someone else, other than the process identity, and access local resources.
Moving onto delegation, the dictionary meaning is something like “empowering someone to act on behalf of another”. A analogy with legal world is the power of attorney, which confers legal rights on someone to take decisions on behalf of someone else. The key difference to note here is that we know that this is another person that whom we are expecting, but this other person has been given rights to act on behalf of the person we were expecting. Just like impersonation required ID and password, delegation, will also require this other person to carry some credentials. Here however the requirement is dual. The person being delegated may have to prove his/her own identity and also show some evidence of being delegating on behalf of someone else.
In application development, delegation comes into picture when there is a machine-hop. Mostly typically this is seen when a client connects to an ASP.NET application on a web server and then a request is sent across the machine to either application tier or database tier. The web server, in this case needs to authenticate with the application tier or database tier on behalf of the user. This can be done by the web server by passing the ID and password to the next tier or look for some other mechanism by using some third party intermediary.
Since we are talking about web applications, let’s take the various authentication mechanisms possible and then discuss how that impacts delegation.
Anonymous: In this there is no credentials recorded from the logged in user and hence the web server has no data to share with next tier and thus delegation isn’t possible. In this case, it is the ASP.NET process identity that can be used for further delegation or impersonation of specific account be done using web.config file.
Basic: User is authenticated by taking the ID and password in clear text and this the web server can easily pass onto the next tier and hence delegation is possible.
Digest: User is authenticated by taking the ID and password, but it is encoded and hence the web server can’t pass these further. Thus delegation isn’t possible.
Windows: User is authenticated by taking the domain credentials by doing a handshake between client and server without really exchanging password. Web server only has access to ID and hence delegation isn’t possible.
Forms: User is authenticated by taking ID and password and depending on what encryption mechanism is used, these can be passed further and delegation may be possible.
Kerberos: Extension to Windows authentication (NTLM) where-by web server is authenticated by a third party and is also given rights to delegate on behalf of logged in users. The web server credentials provided by the third party are taken as evidence for right to delegate and hence delegation becomes possible. The rights to delegate are configured in AD. The default NETWORK SERVICE account under which ASP.NET runs has delegation rights.
In summary delegation is authentication across machine boundary on behalf of someone else.
Another important aspect is do impersonation and delegation work together? Well, they can, but not necessary. If you want to authenticate to the remote machine using the same identity as that used to log into the first machine (web server) then impersonation and delegation go hand in hand, else not. This may not be a good idea. Take for example accessing a database on remote machine. If we impersonate and delegate, all valid users of the application will need to be granted rights on the database and this can easily become a maintenance nightmare. This also additionally works against connection pooling, though gives benefit in terms of maintaining appropriate audit trail. Usually following approaches are possible
1. Use trusted connection, where the identity of the application pool is set to a domain account and this same account is granted appropriate rights to the database. This domain account will need to be granted Kerberos authentication rights by creating appropriate SPN in AD.
2. Use specific impersonation account. Same as previous point, but the credentials in this case come from the web.config file of the web server. This is using SQL authentication.
3. Create specific read/write type accounts in SQL and they are used from the code. Using different read and write accounts enforces additional security based on which account is used to authenticate with database.
That's it for this discussion. I would be interested in any comments you may have to share on this topic.