ASP.NET 2.0 Security Questions and Answers - Impersonation / Delegation

From Guidance Share

Jump to: navigation, search

Contents

When do I use impersonation in ASP.NET 2.0?

You should use impersonation in an ASP.NET application when you need to access local resources using security context of the original caller or a fixed identity.


Impersonation of the authenticated caller is established with the following configuration

<identity impersonate="true"/>


By default any resources accessed by ASP.NET application are accessed under the security context of the ASP.NET process identity. In IIS 6.0 that is the NT Authority\Network Service account by default. Furthermore, impersonation can be fixed for the lifetime of the entire HTTP request or it can be enabled programmatically.


More Information

For more information on using impersonation, see “How To: Use Impersonation and Delegation in ASP.NET 2.0” at http://msdn.microsoft.com/library/en-us/dnpag2/html/PAGHT000023.asp


How do I impersonate the original caller?

ASP.NET does not impersonate the original caller by default. If you need to impersonate the original caller, set the mode attribute of the <authentication> element in the Web.config file to Windows and the impersonate attribute of the <identity> element to true. In IIS, disable anonymous access and select Integrated Windows authentication mechanism. If you do not do this, the ASP.NET application will impersonate the anonymous IIS account IUSR_machineName.


Impersonate original caller to access all the local resources from ASP.NET application using original user’s security context. With impersonation you can use operating system auditing because you can track which users have attempted to access specific resources. You can also enforce access controls on the resources for individual user accounts.


For impersonating original caller, configure the web.config as follows.

 <authentication mode="Windows" />
 <identity impersonate="true" />


More Information

For more information on using impersonation, see “How To: Use Impersonation and Delegation in ASP.NET 2.0” at http://msdn.microsoft.com/library/en-us/dnpag2/html/PAGHT000023.asp


How do I temporarily impersonate the original caller?

To temporarily impersonate the original caller in your application's Web.config file, set the mode attribute of the <authentication> element to Windows and the impersonate attribute of the <identity> element to false. In IIS, disable anonymous access and select Integrated Windows authentication mechanism.


If your application is such that it uses the ASP.NET worker process Identity for the most part and needs to use original users security context for accessing specific resources or perform specific operation. You should temporarily impersonate the original caller.


Here is how you impersonate the original caller temporarily

  • Configure web.config file as follows
     <authentication mode="Windows" />
     <identity impersonate="false" />
    
  • Use following code for impersonating the original caller
     using System.Security.Principal;
     ….
     // Obtain the authenticated user's Identity token
     WindowsIdentity winId =(WindowsIdentity)
     HttpContext.Current.User.Identity;
     WindowsImpersonationContext ctx = winId.Impersonate();
     // Access resources using the identity of the authenticated 
     // user
     // Revert impersonation
     ctx.Undo();
    


More Information

For more information on using impersonation, see “How To: Use Impersonation and Delegation in ASP.NET 2.0” at http://msdn.microsoft.com/library/en-us/dnpag2/html/PAGHT000023.asp


How do I impersonate a specific (fixed) identity?

If you need to impersonate a specific (fixed) identity, set the impersonate attribute to true and supply the identity credentials using username and password attributes of the <identity> element.


Impersonate specific or fixed identity to access all the local resources from ASP.NET application using original user’s security context.


Important: Ideally you should not use fixed identity impersonation, instead create a application pool running under that identity and assign your application to the application pool. As impersonation carries lot of overhead and should be used only when required.


For impersonating a fixed windows identity, configure the web.config as follows.

 <authentication mode="Windows" />
 <identity impersonate="true" username="UserName" password="P@ssw0rd" />


More Information

For more information on using impersonation, see “How To: Use Impersonation and Delegation in ASP.NET 2.0” at http://msdn.microsoft.com/library/en-us/dnpag2/html/PAGHT000023.asp


When should I use programmatic impersonation?

If your application is such that it uses the ASP.NET worker process Identity for the most part and you only want to temporarily impersonate the original caller (or any other identity) to perform specific set of operations or access specific resources, you should use programmatic impersonation.


More Information

For more information on using programmatic impersonation, see “How To: Use Impersonation and Delegation in ASP.NET 2.0” at http://msdn.microsoft.com/library/en-us/dnpag2/html/PAGHT000023.asp


How do I use programmatic impersonation?

There are two approaches to using programmatic impersonation in your code and these are based on which form of authentication your ASP.NET application employs. For both cases however, you need to ensure that ASP.NET built-in impersonation is disabled. This, you can specify in the web.config file.

 <identity impersonate="false">


If your ASP.NET web application uses Windows authentication, then to use programmatic impersonation, you need to obtain the WindowsIdentity object from HTTPContext.User. This WindowsIdentity represents the authenticated user. You need then call its Impersonate method as shown below:

 WindowsIdentity winId = (WindowsIdentity)HttpContext.Current.User.Identity;
 WindowsImpersonationContext ctx = null;
 try
 {
  // Start impersonating
  ctx = winId.Impersonate();
  // Now impersonating
  // Access resources or perform operation impersonated security context
 }
 finally
 {
  // Revert impersonation
  if (ctx != null)
    ctx.Undo();
 }
 // Back to running under the default ASP.NET process identity


If your ASP.NET web application uses custom authentication, such as Forms authentication, you must programmatically create a WindowsIdentity object for the caller, which you can then use to impersonate the caller. For this you have two options, depending on your deployment environment

  • Use the Win32 LogonUser API (via P/Invoke)
  • Use new WindowsIdentity constructor passing in the user principal name (UPN) for the account. This feature is only available in windows server 2003. An example of this is shown below


Important: Your process identity should have TCB permission for using the new WindowsIdentity constructor to get impersonation level token.


Here is sample code for using WindowsIdentity constructor

 using System.Security.Principal;
 …. 
 // Obtain the user Identity token using
 // WindowsIdentityConstructor
 WindowsIdentity winId = new WindowsIdentity(
 userName@fullyqualifieddomainName);
 WindowsImpersonationContext ctx = winId.Impersonate();
 // Access resources using the identity of the impersonated user 
 // Revert impersonation
 ctx.Undo();


More information

For more information on using programmatic impersonation, see “How To: Use Impersonation and Delegation in ASP.NET 2.0” at http://msdn.microsoft.com/library/en-us/dnpag2/html/PAGHT000023.asp


What is protocol transition and when do I care?

Protocol transition is a new feature introduced in Windows Server 2003, which enables applications to use non-Windows authentication mechanism to authenticate users with windows accounts at front tier and transition to Kerberos authentication in middle tier.


You can use protocol transition in scenarios where it’s not possible for your web application to authenticate your users using Kerberos authentication, although your users have windows accounts. For example, firewalls prevent direct communication with the domain controller. In such scenarios Forms authentication or client certificate authentication are used instead. In these scenarios protocol transition is used for changing to Kerberos authentication at the backend for accessing network resources using delegation.


More Information

For more information on using protocol transition, see “How To: Use Protocol Transition and Constrained Delegation in ASP.NET 2.0” at http://msdn.microsoft.com/library/en-us/dnpag2/html/PAGHT000024.asp


What is Constrained Delegation?

Kerberos delegation on Windows Server 2000 is unconstrained and servers that are configured as trusted for delegation in Active Directory can access any network resources or any machine on the network while using the impersonated user's security context. This represents a potential security threat, particularly if the Web server is compromised.


To address this issue, Windows Server 2003 introduces constrained delegation. This allows administrators to specify exactly which services on a downstream server or a domain account can access when using an impersonated user's security context.


Note: The list of services that can be accessed by delegation is maintained in an Active Directory list referred to as the A2D2 list.


More Information

For more information on how to use constrained delegation, see “How To: Use Protocol Transition and Constrained Delegation in ASP.NET 2.0” at http://msdn.microsoft.com/library/en-us/dnpag2/html/PAGHT000024.asp


How can I retain impersonation in the new thread created from ASP.NET application?

In .NET Framework 1.1, impersonation tokens did not automatically flow to newly created threads. This situation could lead to security vulnerabilities because new threads assume the security context of the process. In .NET Framework 2.0, by default the impersonation token still does not flow across threads, but for ASP.NET applications you can change this default behavior with appropriate configuration of the ASPNET.config file in the %Windir%Microsoft.NET\Framework\{Version Number\ directory.


If you need to flow the impersonation token to new threads, set the enabled attribute to true on the alwaysFlowImpersonationPolicy element and enabled attribute to false on legacyImpersonationPolicy element.in the ASPNET.config file, as shown in the following example.

 <configuration>
  <runtime>
    <alwaysFlowImpersonationPolicy enabled="true"/>
    <legacyImpersonationPolicy enabled="false"/>
  </runtime>
 </configuration>


If you need to prevent impersonation tokens from being passed to new threads programmatically, you can use the ExecutionContext.SuppressFlow method.


How do I flow the original user identity to different layers?

Use Kerberos delegation to flow the original caller identity to a backend resource either for per-user authorization or to use operating system auditing.

To use Kerberos authentication

  • All computers must be in the same Active Directory forest or in domains in separate forests with trust relationships.
  • You must configure the Web server or application server machine accounts in Active Directory for delegation. Alternatively, if your ASP.NET application runs under a specific custom domain account, you can configure the domain account for delegation.
  • IIS must be configured for Windows authentication, or for certificate authentication with certificate mapping.
  • You must enable impersonation in your applications Web.config (see "How to impersonate the original caller").


You should use Windows Server 2003 constrained delegation to restrict which server and which service the impersonated account can access.

To use constrained delegation

  • On the domain controller, run the Active Directory Users and Computers MMC snap in from Administrative Tools.
  • In the left-hand pane, click on the root node titled Active Directory User and Computers [machinename.domain].
  • Select Action | All Tasks | Raise Domain Functional Level from the menu bar.
  • Select Windows Server 2003 in the Select an available domain functional level dropdown box.
  • Configure the Web server machine account to be trusted for constrained delegation to the Application server.
  • In the left-hand pane of the Active Directory Users and Computers MMC snap in, click on the Computers node.
  • In the right-hand pane, double-click the WEB computer.
  • On the Delegation tab, select Trust this computer for delegation to specified services only (constrained delegation).
  • Click Add.
  • In the Add services dialog, click Users or computers.
  • In the Select Users or Computers dialog, enter the name of the Application server and click OK.
  • In the Add services dialog, you will now see all the available services on the WEB server. Select the HTTP service and click OK.


Can impersonation be used with Forms authentication?

Yes, you can either use protocol transition, if you're running on Windows Server 2003, or you can call LogonUser.


If you need to delegate the original caller's identity on machines that are not running Windows Server 2003, or where you cannot use Kerberos authentication, then you need to use the LogonUser API.


To use the LogonUser API

  • Use Forms authentication to obtain the username, password and domain from the user.
  • Grant the Act as part of the operating system privilege (TCB) to the account used to run ASP.NET on the Web server (the Network Service account by default).
  • Add a DllImport definition for LogonUser (advapi32.dll) and CloseHandle (kernel32.dll)
  • Call the LogonUser method, passing the user ID, password, and domain. Also request a network logon type. This method returns the impersonation token as an output parameter.
  • Use the impersonation token to create a Windows identity and impersonate that identity.
  • When you have completed your resource access, remove the impersonation token from the current thread and call CloseHandle to close the impersonation token.


For example:

 using System.Runtime.InteropServices;
 …
 // Declare the logon types as constants
 const long LOGON32_LOGON_NETWORK = 3;

 // Declare the logon providers as constants
 const long LOGON32_PROVIDER_DEFAULT = 0;


 [DllImport("advapi32.dll",EntryPoint = "LogonUser")]
 private static extern bool LogonUser(
            string lpszUsername,
            string lpszDomain,
            string lpszPassword,
            int dwLogonType,
            int dwLogonProvider,
            ref IntPtr phToken);
 [DllImport("kernel32.dll", CharSet=CharSet.Auto)]
 public extern static bool CloseHandle(IntPtr handle);
 

 private void ImpersonateAndUse(string Username,
                                         string Password,
                                         string Domain)
 {
   IntPtr token = new IntPtr(0);
   token = IntPtr.Zero;

   // Call LogonUser to obtain a handle to an access token.
   bool returnValue = LogonUser(Username, Domain,Password,
                                  (int)LOGON32_LOGON_NETWORK,
                                  (int)LOGON32_PROVIDER_DEFAULT,
                                  ref token);
   if (false == returnValue)
   {
      int ret = Marshal.GetLastWin32Error();
      string strErr = String.Format("LogonUser failed with error code : {0}", ret);
      throw new ApplicationException(strErr, null);
   }
   WindowsIdentity newId = new WindowsIdentity(token);
   WindowsImpersonationContext impersonatedUser = newId.Impersonate();
   try
   {
      // do the operations using original user security context
   }
   finally
   {
      // stop impersonating
      impersonatedUser.Undo();
      CloseHandle(tokenHandle); // From where did this variable "tokenHandle" came from?
   }
 }


What are the requirements for using Kerberos delegation?

  • For Kerberos delegation the server should be part of the domain.
  • ASP.NET Process Identity of the server or the Server account in the domain should be configured for delegation.
  • The client and server both should kerberos authetication.
Personal tools