Impersonation/Delegation

patterns & practices Developer Center

  • What are my impersonation options?
  • What is the difference between impersonation and delegation?
  • How do I impersonate the original caller for an operation call?
  • How do I temporarily impersonate the original caller in an operation call?
  • How do I impersonate a specific (fixed) identity?
  • What is constrained delegation?
  • What is protocol transition?
  • How do I flow the original caller from the ASP.NET client to a WCF service?
  • What is the difference between declarative and programmatic impersonation?
  • What is the trusted subsystem model?
  • When should I flow the original caller to back-end code?
  • How do I control access to a remote resource based on the original caller's identity?

What are my impersonation options?

There are three options for impersonation:

  • Impersonating the original caller declaratively on specific operations. Use this option when you want to impersonate the original caller for the entire duration of a specific operation.
  • Impersonating the original caller declaratively on the entire service. Use this option when you want to impersonate the original caller for the entire duration of all operations in the service.
  • Impersonating the original caller programmatically within an operation. Use this option when you want to impersonate the original caller for a short duration in a service operation.

Additional Resources

What is the difference between impersonation and delegation?

Impersonation flows the original caller's identity to back-end resources on the same computer. Delegation flows the original caller's identity to back-end resources on computers other than the computer running the service.

For example, if a service is running within IIS without impersonation, the service will access resources using the ASP.NET account in IIS 5.0, or the Network Service account in IIS 6.0. With impersonation, if the client is connecting using the original caller's account, the service will access resources such as a SQL Server database on the same machine using the original caller's account instead of the system ASP.NET account. Delegation is similar except that the SQL Server database could be on a different machine that is remote to the service.

Additional Resources

How do I impersonate the original caller for an operation call?

Because impersonation is a costly operation and is usually used for higher-privileged original callers, you should use impersonation only on operations that need it to reduce the potential attack surface.

You can impersonate declaratively by applying the OperationBehaviorAttribute attribute on any operation that requires client impersonation, as shown in the following code example:

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public string GetData(int value)
{
   return “test”;
}

Additional Resources

How do I temporarily impersonate the original caller in an operation call?

Because impersonation is a costly operation and is usually used for higher-privileged original callers, you should use impersonation only when it is needed to reduce the potential attack surface. Programmatic impersonation allows you to impersonate on specific lines of code rather than the entire operation.

You can use programmatic impersonation to temporarily impersonate the original caller in an operation call, as shown in the following example:

public string GetData(int value)
{
 using (ServiceSecurityContext.Current.WindowsIdentity.Impersonate())
 {
     // return the impersonated user (original users identity)
     return string.Format("Hi, {0}, you have entered: {1}",
          WindowsIdentity.GetCurrent().Name, value);
 }   
}

In the above example, the using statement is employed to ensure that the impersonation is reverted after execution of the using block. It is important to revert impersonation because failure to do so can form the basis for denial of service (DoS) and elevation of privilege attacks.

Additional Resources

How do I impersonate a specific (fixed) identity?

Use the WindowsIdentity class to obtain a Windows token and logon session for a given domain account by supplying a user principal name (UPN). With this approach, you do not need the account's password.

using System.Security.Principal;
…
WindowsIdentity wi = new WindowsIdentity(userName@fullyqualifieddomainName);
WindowsImpersonationContext ctx = null;

try
{
  ctx = wi.Impersonate();
  // Thread is now impersonating you can call the backend operations here...

catch
{
  // Prevent exceptions propagating.
}
finally
{
  // Ensure impersonation is reverted
  ctx.Undo();
}

Note

The WindowsIdentity constructor relies on a Windows Server 2003 extension to the Kerberos protocol called Service for User to Self (S4U2Self). You can use this approach if your application runs on a Windows Server 2003 server in a Windows Server 2003 domain. The advantage of this approach is that you do not have to store credentials as you do for LogonUser.

Additional Resources

What is constrained delegation?

Impersonation is a WCF service configuration in which the service will access resources on the same computer using a client's user identity. Delegation is similar to impersonation except that the WCF service can access resources that are on the same machine or on other machines using the client's user identity. Delegation flows the original caller's identity to back-end resources on the computers other than the computer running the service.

The Microsoft Windows Server 2003 operating system provides a more secure form of delegation called constrained delegation. With constrained delegation, you can configure the Microsoft Active Directory directory service to restrict the services and servers that your WCF service application can access with the impersonated identity. Constrained delegation in Windows Server 2003 requires Kerberos authentication.

Additional Resources

What is protocol transition?

Protocol transition is a Windows Server 2003 feature that allows you to switch from an alternate, non-Windows authentication mode (such as Forms-based or certificate authentication) to Kerberos authentication. This is useful when your application cannot use Kerberos authentication to authenticate its callers, and when your application needs to use constrained delegation to access downstream network resources.

Additional Resources

How do I flow the original caller from the ASP.NET client to a WCF service?

The following steps show how to impersonate the original caller from the ASP.NET client to a WCF service:

  1. Configure your WCF service to use Windows authentication.

    …
    <services>
      <service name="Service" behaviorConfiguration="ServiceBehavior">
        <endpoint address="" binding="wsHttpBinding" contract="IService">
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding"
             contract="IMetadataExchange"/>
      </service>
    </services>
    …
    
  2. Configure the SPN identity for the WCF service endpoint.

        <endpoint address="" binding="wsHttpBinding" contract="IService">
          <identity>
            <servicePrincipalName value="HOST/YourMachineName" />
            <dns value="" />
          </identity>
        </endpoint>
    
  3. Implement impersonation in the WCF service.

    using System.Security.Principal;
    [OperationBehavior(Impersonation = ImpersonationOption.Required)]
    public string GetData(int value)
    {
      return string.Format("Hi, {0}, you have entered: {1}",
                               WindowsIdentity.GetCurrent().Name, value);
    }
    
  4. Create a Web application test client and add the WCF service reference.

  5. Impersonate the original caller when calling the WCF service.

    using System.Security.Principal;
    …
    protected void Button1_Click(object sender, EventArgs e)
    {
        // Obtain the authenticated user's Identity and impersonate the original caller
        using (((WindowsIdentity)HttpContext.Current.User.Identity).Impersonate())
        {
            WCFTestService.ServiceClient myService = new WCFTestService.ServiceClient();
            Response.Write(myService.GetData(123) + "<br/>");
            myService.Close();
        }
    }
    …
    
  6. Configure the Web application for constrained delegation.

    • If your ASP.NET application runs using the Network Service machine account, you must enable constrained delegation for your Web server computer.
    • If your ASP.NET application runs under a custom domain account, you must enable protocol transition and constrained delegation for the custom domain account.
  7. Test the client and WCF service.

Additional Resources

What is the difference between declarative and programmatic impersonation?

Impersonation is used to restrict or authorize the original caller's access to a WCF service's local resources, such as files. Use declarative impersonation to define impersonation at the operation or service level.

Impersonate declaratively by applying the OperationBehaviorAttribute attribute on any operation that requires client impersonation, as shown in the following code example:

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public string GetData(int value)
{
   return “test”;
}

Use programmatic impersonation to define finer-grained impersonation based on business logic. Programmatic impersonation is specified in code and applied at run time.

Programmatic impersonation can be performed as shown in the following example:

public string GetData(int value)
{
 using (ServiceSecurityContext.Current.WindowsIdentity.Impersonate())
 {
     // return the impersonated user (original users identity)
     return string.Format("Hi, {0}, you have entered: {1}",
          WindowsIdentity.GetCurrent().Name, value);
 }   
}

Additional Resources

What is the trusted subsystem model?

A trusted subsystem describes an architecture in which an upstream tier is trusted to authenticate and authorize the original caller for downstream components. For instance, a database server trusts the Web application to authenticate users, and then all calls from the Web application to the database server are made with the Web application's identity instead of the original caller's identity. In this model, the web application's identity is trusted to make calls on behalf of the original caller.

The advantages of the trusted subsystem model include support for efficient connection pooling, no direct data access because only the service account is granted access to the back-end resources, and minimal back-end access control list (ACL) management.

Additional Resources

When should I flow the original caller to back-end code?

Flow the original caller to back-end code when you need to authorize access to resources based on the original caller's identity, or when the back-end code needs to perform roles-based authorization.

Additional Resources

How do I control access to a remote resource based on the original caller's identity?

Use delegation to flow the impersonated original user's security context (Windows identity) to the remote back-end service. On the remote back-end service, the original user's Windows identity can be used to authenticate or impersonate the original caller in order to restrict or authorize the original caller's access to local resources.

When using delegation on Windows Server 2003 or later, use constrained delegation. This allows administrators to specify exactly which services can be accessed on a downstream server or a domain account when using an impersonated user's security context.

Additional Resources