Learning Impersonation in WCF services

 

What is Impersonation ?

Ability of a thread to execute in a security context that is different from the context of the process that owns the thread

When running in a client's security context, a service "is" the client, to some degree.

 

Why we need it ?

We require impersonation, to use the original caller’s identity for authorizing access to service resources.

Note: Impersonation is used to access resources on the same machine as the service, while delegation is used to access resources that are remote to the service

 

  Understanding Impersonation Level (WCF Service)

  1. NotAllowed: Impersonation is not performed in a particular operation.
  2. Allowed : Impersonation is performed if the original Windows token is available and the service is configured to impersonate on all operations using ImpersonateCallerForAllOperations in ServiceAuthorizationBehavior.
  3. Required: Impersonation is performed; the Windows identity token is required to be available.

 

 Understanding Impersonation Level (WCF Client)

  1. None:  The WCF service cannot authenticate or impersonate the user.
  2. Anonymous:  The WCF service authenticates clients as anonymous, but cannot obtain information for identification or impersonation.
  3. Identification:  The WCF service can authenticate clients and get information for identification, but cannot impersonate the clients. This is the default value.
  4. Impersonation: The WCF service can authenticate, get information for identification, and impersonate clients on local systems.
  5. Delegation:  The WCF service can authenticate, get information for identification, and impersonate clients on local as well as remote systems.

 

 Once we understand the requirement and importance of the impersonation, let us see the basic requirement to set and use the same.

  

Consider that the WCF service and client application (web app) - running on same box – hosted on IIS.

(impersonation is limited to a single machine/box)

 

WCF Service

  1. Setting the impersonation level
    1. Via Operation attribute:

Impersonate the Original Caller Declaratively on Specific Operations

[OperationBehavior(Impersonation = ImpersonationOption.Required)]

public string GetData(int value)

{

   return “test”;

}

b. Via configuration file

Impersonate the Original Caller Declaratively for the Entire Service (We can set this in the WCF configuration file)

<behaviors>

  <serviceBehaviors>

    <behavior name="ServiceBehavior">

      <serviceMetadata httpGetEnabled="true" />

      <serviceDebug includeExceptionDetailInFaults="false" />

      <serviceAuthorization impersonateCallerForAllOperations="true" />

    </behavior>

  </serviceBehaviors>

</behaviors>

C. Within a operation

Impersonate the Original Caller Programmatically Within an Operation

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);

}  

}

  

To retrieve the identity on server. Windows Identity Class:  http://msdn.microsoft.com/en-us/library/system.security.principal.windowsidentity.aspx

 We can use System.Security.Principal.WindowsIdentity.GetCurrent().Name to retrieve the current windows identity impersonated from WCF client application.

 

 WCF Client application (Web app in this scenario) 

 Setting the impersonation level:

Can be done in configuration file on client side or at the time of proxy creation.

Configuration file

<behaviors>

           <endpointBehaviors>

              <behavior name=""ImpersonationBehavior"">

                 <clientCredentials>

                      <windows allowedImpersonationLevel=""Impersonation"" />

                 </clientCredentials>

              </behavior>

           </endpointBehaviors>

        </behaviors>

 Default is Identification.

 Or At the time of proxy creation

proxy.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;

 

 Note: if client application is Web application

Then set:

<identity impersonate="true"/>

 

Note:

The IIS web applications should be configured to allow impersonation, then only we can get the identity of user who is accessing the web app page via browser. Once we get the identity we can use it / impersonate it to the WCF process on same machine.

 

 

Web applications

http://msdn.microsoft.com/en-us/library/134ec8tc.aspx

 Windows identity supplied by IIS to the User property of the current HttpContext object

<configuration>

  <system.web>

    <identity impersonate="true" />

  </system.web>

</configuration>

 

IIS Settings

  

  1. Disable Anonymous
  2. Enable ASP.NET Impersonation
  3. Enable Windows Authentication

 

 

Application Pool

 Make sure it is running under Classic mode.


  

On Website layer, Make sure no “Physical path credential ” are specified.

 

   

Important: 

1. Impersonation related settings can be used for playing with credentials on the local box.

For example:   Box1 (Web App) -> Box1 (WCF Service)

 2.  If we need to access any other service on a different box, then we have to delegate the credentials.

For example:   Box1 (Web App) -> Box2 (WCF Service)

 

 Hope this will help in getting started with impersonation.