views:

263

answers:

5

Here's a simple question I've been stuck on for a while.

When I set < identity impersonate=true > in my web.config so that asp.net impersonates the logged on user automatically (or the anonymous account if not using Windows Authentication), where does the identity that asp.net impersonates come from?

This document: http://msdn.microsoft.com/en-us/library/ff649264.aspx shows three places you can retrieve information about the logged on user:

  • Httpcontext.Current.user
  • System.Threading.Thread.Current
  • System.Security.Principal.WindowsIdentity.GetCurrent
  • It seems that none of these locations consistently match the identity that gets impersonated when I set < identity impersonate=true > in web.config.

    I would like to know where the impersonated identity comes from.

    Specifically, I mean to ask at a low level, where exactly does the identity get retrieved from at run-time. I am familiar with the configuration of IIS, but I want to know how the identity is retrieved at run-time and where it comes from. For the sake of discussion, let's suppose that the identity is set in IIS, not in the web.config file.

    A: 

    If I'm not mistaken, this is the identity set in IIS. Directory security.

    aepheus
    Not the answer I'm looking for - This answer sets how to set the identity in the configuration. I want to know where it is retrieved from at runtime.
    Rice Flour Cookies
    Try Environment.UserName
    aepheus
    A: 

    In the past I've set the identity to impersonate in the web.config file. In this case I created a user, set the application pool to be under that user, and used that user name for impersonation.

    aron
    still not the answer I'm looking for. I am *not* asking about how to configure impersonation. I know how to do that. I am asking where does the impersonated identity come from at run-time?
    Rice Flour Cookies
    +6  A: 

    When impersonation is enabled, the identity comes from IIS. What happens is that ASP.NET impersonates the access token that IIS provides.

    The original access token that was used to run the process to start with is still available. This is likely the source of confusion around the use of the three API's mentioned in the question.

    Thread.CurrentPrincipal & HttpContext.Current.User: The identity of the user on the other end of the line.

    • This is the information passed to ASP.NET via the impersonation token
    • This token becomes the identity created dynamically based on:
    • either: a) how the user logged in (Forms vs. Windows Authentication),
    • or: b) what the impersonation userName setting was in the web.config.

    WindowsIdentity.GetCurrent: The actual underlying Windows account that is executing.

    • This is how the process was started before ASP.NET started impersonation.
    • This will only be a WindowsIdentity.

    The reason for the duplication in HttpContext.Current.User is a convenience to ASP.NET developers.

    Edit:

    When IIS is configured to run under Integrated Windows Authentication, and ASP.NET has impersonation enabled, the following code will enable us to run code as the underlying account.

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool RevertToSelf();
    
    protected void Page_Load(object sender, EventArgs e)
    {
        var me = WindowsIdentity.GetCurrent();
    
        // At this point:
        // me.Name = Domain\UserName
        // me.AuthenticationType = Kerberos
    
        if (RevertToSelf())
        {
            var underMe = WindowsIdentity.GetCurrent();
            // At this point:
            // underMe.Name = IIS APPPOOL\DefaultAppPool
            // underMe.AuthenticationType = Negotiate
        }
    }
    

    Depending on what you are trying to do, this page has more ways of attacking the problem: http://support.microsoft.com/kb/306158

    umbyersw
    You say that the original access token that was used to run the process is used for impersonation... I assume that you mean the IIS process. However, I'm not sure how this could be given that if you configure IIS to use `Windows Authentication`, then IIS will impersonate with the logged on user's token.
    Rice Flour Cookies
    If you look at this doc: http://msdn.microsoft.com/en-us/library/ff649264.aspx, you'll see that according to MS, `WindowsIdentity.GetCurrent` is the only one of the three API usernames that changes when we use impersonation.
    Rice Flour Cookies
    To clarify, what I said was: "The original access token that was used to run the process to start with is still available."And yes, now we have two Windows Identities... I'll edit my answer to include some sample code around how to switch back to the underlying Windows Account.
    umbyersw
    A: 

    If you are having concern on the which entity having the effect on your application, first thing to be noted is the Mode of your authentication like (Windows, Form, Passport or None)

    the loaction where from the credentials read for authendicating your request is depends on your authentication mode selected for your application.

    Dharma
    +3  A: 

    You cannot separate the impersonation-part from the authentication-part. I think you know that since you write

    ... asp.net impersonates the logged on user automatically (or the anonymous account if not using Windows Authentication)...

    But I am confused by the sentence

    For the sake of discussion, let's suppose that the identity is set in IIS, not in the web.config file.

    What exactly do you mean by this?

    But let me have a shot at an answer anyway:
    Let's assume you are using IntegratedWindowsSecurity, <identity impersonate=true> and <authentication mode=Forms> in Web.config. This would correspond to the second-last row of the last table in Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication which you cited.

    It states that Domain\UserName will be returned from WindowsIdentity in this case. And I assume you are wondering where that Domain\UserName-Identity comes from... There are some restrictions on using Kerberos like IE has to classify the URL as "Intranet" or "Local" but I think this is not important here.

    Now it is important to distinguish between setting <authentication mode=windows> in Web.config and setting the access mode to IntegratedWindowsSecurity (or whatever it is called) in IIS. Being in the last table of aforementioned link we are in the situation of IIS being set to IntegratedWindowsSecurity (nevertheless we can set <authentication mode="windows"> in Web.config!). So IE negotiates with IIS on how to authenticate the currently logged in user. Either using NTLM or Kerberos (mainly depending on the Windows version). That is where the Domain\UserName comes from.

    The following article (talking about delegation, I know) might shed more light on the issue ASP.NET Delegation:

    Integrated Windows Authentication

    When Internet Explorer attempts to access a protected resource, IIS sends two WWW-Authenticate headers to the browser, Negotiate and NTLM. The Negotiate header is only sent by IIS running on Windows 2000 or later. This header indicates that IIS supports the Negotiate protocol, which enables a negotiation to occur between Internet Explorer and IIS on whether to use Kerberos or NTLM authentication. IIS uses Kerberos if both the client (Internet Explorer 5.0 and later) and server (IIS 5.0 and later) are running Windows 2000 or later, and both are members of the same domain or trusted domains. Otherwise, the server defaults to using NTLM.

    Since NTLM authenticates the user for IIS without providing the user's credentials to IIS, IIS cannot delegate that user's credentials to a remote machine.

    When used in conjunction with Kerberos v5 authentication, IIS can delegate security credentials among computers running Windows 2000 or later that are trusted and configured for delegation.

    You probably know these links but I am posting them anyway:

    EDIT:
    To be a bit more precise I think (not sure here) that IIS creates the WindowsIdentity from a LogonToken (the one you get by calling unmanaged Win32 LogonUser function) using the constructor explained here in msdn. Also the example code in the documentation of the WindowsIdentity Class is quite interesting (IntPtrStringTypeConstructor for example). The logon token would have to come from IE then.

    Scott Hanselman wrote about a similar thing also: System.Threading.Thread.CurrentPrincipal vs. System.Web.HttpContext.Current.User or why FormsAuthentication can be subtle.

    And I think you might be able to extract additional information if you look for solutions to "implant" a custom principal object into ASP.NET authentication process (usually using Application_AuthenticateRequest in Global.asax). Like Using Custom Principal with Forms Authentication in ASP.NET for example.

    Or you can use Reflector and see for yourself :)

    scherand
    You can separate authentication and impersonation, but you have to do it yourself, instead of using the ASP.NET configuration. See this article for various examples: http://support.microsoft.com/kb/306158.
    umbyersw