Delegation and Impersonation with WCF

Impersonation is a common technique that services use to restrict client access to a service domain's resources. Service domain resources can either be machine resources, such as local files (impersonation), or a resource on another machine, such as a file share (delegation). For a sample application, see Impersonating the Client Sample. For an example of how to use impersonation, see How to: Impersonate a Client on a Service.

ms730088.Important(en-us,VS.90).gif Note:
Be aware that when impersonating a client on a service, the service runs with the client's credentials, which may have higher privileges than the server process.

Overview

Typically, clients call a service to have the service perform some action on the client’s behalf. Impersonation allows the service to act as the client while performing the action. Delegation allows a front-end service to forward the client’s request to a back-end service in such a way that the back-end service can also impersonate the client. Impersonation is most commonly used as a way of checking whether a client is authorized to perform a particular action, while delegation is a way of flowing impersonation capabilities, along with the client’s identity, to a back-end service. Delegation is a Windows domain feature that can be used when Kerberos-based authentication is performed. Delegation is distinct from identity flow and, because delegation transfers the ability to impersonate the client without possession of the client’s password, it is a much higher privileged operation than identity flow.

Both impersonation and delegation require that the client have a Windows identity. If a client does not possess a Windows identity, then the only option available is to flow the client’s identity to the second service.

Impersonation Basics

Windows Communication Foundation (WCF) supports impersonation for a variety of client credentials. This topic describes service model support for impersonating the caller during the implementation of a service method. Also discussed are common deployment scenarios involving impersonation and SOAP security and WCF options in these scenarios.

This topic focuses on impersonation and delegation in WCF when using SOAP security. You can also use impersonation and delegation with WCF when using transport security, as described in Using Impersonation with Transport Security.

Two Methods

WCF SOAP security has two distinct methods for performing impersonation. The method used depends on the binding. One is impersonation from a Windows token obtained from the Security Support Provider Interface (SSPI) or Kerberos authentication, which is then cached on the service. The second is impersonation from a Windows token obtained from the Kerberos extensions, collectively called Service-for-User (S4U).

Cached Token Impersonation

You can perform cached-token impersonation with the following:

S4U-Based Impersonation

You can perform S4U-based impersonation with the following:

  • WSHttpBinding, WSDualHttpBinding, and NetTcpBinding with a certificate client credential that the service can map to a valid Windows account.

  • Any CustomBinding that uses a Windows client credential with the requireCancellation property set to false.

  • Any CustomBinding that uses a user name or Windows client credential and secure conversation with the requireCancellation property set to false.

The extent to which the service can impersonate the client depends on the privileges the service account holds when it attempts impersonation, the type of impersonation used, and possibly the extent of impersonation the client permits.

ms730088.note(en-us,VS.90).gifNote:
When the client and service are running on the same computer and the client is running under a system account (for example, Local System or Network Service), the client cannot be impersonated when a secure session is established with stateful Security Context tokens. A Windows Form or console application typically runs under the currently logged-in account, so that account can be impersonated by default. However, when the client is an ASP.NET page and that page is hosted in IIS 6.0 or IIS 7.0, then the client does run under the Network Service account by default. All of the system-provided bindings that support secure sessions use a stateless security context token (SCT) by default. However, if the client is an ASP.NET page, and secure sessions with stateful SCTs are used, the client cannot be impersonated. For more information about using stateful SCTs in a secure session, see How to: Create a Stateful Security Context Token for a Secure Session.

Impersonation in a Service Method: Declarative Model

Most impersonation scenarios involve executing the service method in the caller context. WCF provides an impersonation feature that makes this easy to do by allowing the user to specify the impersonation requirement in the OperationBehaviorAttribute attribute. For example, in the following code, the WCF infrastructure impersonates the caller before executing the Hello method. Any attempt to access native resources inside the Hello method succeed only if the access control list (ACL) of the resource allows the caller access privileges. To enable impersonation, set the Impersonation property to one of the ImpersonationOption enumeration values, either System.ServiceModel.ImpersonationOption.Required or System.ServiceModel.ImpersonationOption.Allowed, as shown in the following example.

ms730088.note(en-us,VS.90).gifNote:
When a service has higher credentials than the remote client, the credentials of the service are used if the Impersonation property is set to Allowed. That is, if a low-privileged user provides its credentials, a higher-privileged service executes the method with the credentials of the service, and can use resources that the low-privileged user would otherwise not be able to use.

Visual Basic
<ServiceContract()>  _
Public Interface IHelloContract
    <OperationContract()>  _
    Function Hello(ByVal message As String) As String 
End Interface


Public Class HelloService
    Implements IHelloService
    
    <OperationBehavior(Impersonation := ImpersonationOption.Required)>  _
    Public Function Hello(ByVal message As String) As String Implements IHelloService.Hello
        Return "hello"
    End Function 
End Class 
C#
[ServiceContract]
public interface IHelloContract
{
    [OperationContract]
    string Hello(string message);
}

public class HelloService : IHelloService
{
    [OperationBehavior(Impersonation = ImpersonationOption.Required)]
    public string Hello(string message)
    {
        return "hello";
    }
}

The WCF infrastructure can impersonate the caller only if the caller is authenticated with credentials that can be mapped to a Windows user account. If the service is configured to authenticate using a credential that cannot be mapped to a Windows account, the service method is not executed.

ms730088.note(en-us,VS.90).gifNote:
On Windows XP, impersonation fails if a stateful SCT is created, resulting in an InvalidOperationException. For more information, see Unsupported Scenarios.

Impersonation in a Service Method: Imperative Model

Sometimes a caller does not need to impersonate the entire service method to function, but for only a portion of it. In this case, obtain the Windows identity of the caller inside the service method and imperatively perform the impersonation. Do this by using the WindowsIdentity property of the ServiceSecurityContext to return an instance of the WindowsIdentity class and calling the Impersonate method before using the instance.

ms730088.note(en-us,VS.90).gifNote:
Be sure to use the Visual Basic Using statement or the C# using statement to automatically revert the impersonation action. If you do not use the statement, or if you use a programming language other than Visual Basic or C#, be sure to revert the impersonation level. Failure to do this can form the basis for denial of service and elevation of privilege attacks.

Visual Basic
Public Class HelloService
    Implements IHelloService
    
    <OperationBehavior()>  _
    Public Function Hello(ByVal message As String) As String _
       Implements IHelloService.Hello
        Dim callerWindowsIdentity As WindowsIdentity = _
            ServiceSecurityContext.Current.WindowsIdentity
        If (callerWindowsIdentity Is Nothing) Then
            Throw New InvalidOperationException( _
              "The caller cannot be mapped to a WindowsIdentity")
        End If
        Dim cxt As WindowsImpersonationContext = callerWindowsIdentity.Impersonate()
        Using (cxt)
             ' Access a file as the caller.
        End Using

        Return "Hello"
    
    End Function
End Class 
C#
public class HelloService : IHelloService
{
    [OperationBehavior]
    public string Hello(string message)
    {
        WindowsIdentity callerWindowsIdentity =
        ServiceSecurityContext.Current.WindowsIdentity;
        if (callerWindowsIdentity == null)
        {
            throw new InvalidOperationException
           ("The caller cannot be mapped to a WindowsIdentity");
        }
        using (callerWindowsIdentity.Impersonate())
        {
            // Access a file as the caller.
        }
        return "Hello";
    }
}

Impersonation for All Service Methods

In some cases, you must perform all the methods of a service in the caller’s context. Instead of explicitly enabling this feature on a per-method basis, use the ServiceAuthorizationBehavior. As shown in the following code, set the ImpersonateCallerForAllOperations property to true. The ServiceAuthorizationBehavior is retrieved from the collections of behaviors of the ServiceHost class. Also note that the Impersonation property of the OperationBehaviorAttribute applied to each method must also be set to either Allowed or Required.

Visual Basic
' Code to create a ServiceHost not shown.
Dim MyServiceAuthoriationBehavior As ServiceAuthorizationBehavior 
MyServiceAuthoriationBehavior= serviceHost.Description.Behaviors.Find _
(Of ServiceAuthorizationBehavior)()
MyServiceAuthoriationBehavior.ImpersonateCallerForAllOperations = True
C#
// Code to create a ServiceHost not shown.
ServiceAuthorizationBehavior MyServiceAuthoriationBehavior = 
    serviceHost.Description.Behaviors.Find<ServiceAuthorizationBehavior>();
MyServiceAuthoriationBehavior.ImpersonateCallerForAllOperations = true;

The following table describes WCF behavior for all possible combinations of ImpersonationOption and ImpersonateCallerForAllServiceOperations.

ImpersonationOption ImpersonateCallerForAllServiceOperations Behavior

Required

n/a

WCF impersonates the caller

Allowed

false

WCF does not impersonate the caller

Allowed

true

WCF impersonates the caller

NotAllowed

false

WCF does not impersonate the caller

NotAllowed

true

Disallowed. (An InvalidOperationException is thrown.)

Impersonation Level Obtained from Windows Credentials and Cached Token Impersonation

In some scenarios the client has partial control over the level of impersonation the service performs when a Windows client credential is used. One scenario occurs when the client specifies an Anonymous impersonation level. The other occurs when performing impersonation with a cached token. This is done by setting the AllowedImpersonationLevel property of the WindowsClientCredential class, which is accessed as a property of the generic ChannelFactory class.

ms730088.note(en-us,VS.90).gifNote:
Specifying an impersonation level of Anonymous causes the client to log on to the service anonymously. The service must therefore allow anonymous logons, regardless of whether impersonation is performed.

The client can specify the impersonation level as Anonymous, Identification, Impersonation, or Delegation. Only a token at the specified level is produced, as shown in the following code.

Visual Basic
Dim cf As ChannelFactory(Of IEcho) = New ChannelFactory(Of IEcho)("EchoEndpoint")
cf.Credentials.Windows.AllowedImpersonationLevel = _
System.Security.Principal.TokenImpersonationLevel.Impersonation
C#
ChannelFactory<IEcho> cf = new ChannelFactory<IEcho>("EchoEndpoint");
cf.Credentials.Windows.AllowedImpersonationLevel  = 
    System.Security.Principal.TokenImpersonationLevel.Impersonation;

The following table specifies the impersonation level the service obtains when impersonating from a cached token.

AllowedImpersonationLevel value Service has SeImpersonatePrivilege Service and client are capable of delegation Cached token ImpersonationLevel

Anonymous

Yes

n/a

Impersonation

Anonymous

No

n/a

Identification

Identification

n/a

n/a

Identification

Impersonation

Yes

n/a

Impersonation

Impersonation

No

n/a

Identification

Delegation

Yes

Yes

Delegation

Delegation

Yes

No

Impersonation

Delegation

No

n/a

Identification

Impersonation Level Obtained from User Name Credentials and Cached Token Impersonation

By passing the service its user name and password, a client enables WCF to log on as that user, which is equivalent to setting the AllowedImpersonationLevel property to Delegation. (The AllowedImpersonationLevel is available on the WindowsClientCredential and HttpDigestClientCredential classes.) The following table provides the impersonation level obtained when the service receives user name credentials.

AllowedImpersonationLevel Service has SeImpersonatePrivilege Service and client are capable of delegation Cached token ImpersonationLevel

n/a

Yes

Yes

Delegation

n/a

Yes

No

Impersonation

n/a

No

n/a

Identification

Impersonation Level Obtained from S4U-Based Impersonation

Service has SeTcbPrivilege Service has SeImpersonatePrivilege Service and client are capable of delegation Cached token ImpersonationLevel

Yes

Yes

n/a

Impersonation

Yes

No

n/a

Identification

No

n/a

n/a

Identification

Mapping a Client Certificate to a Windows Account

It is possible for a client to authenticate itself to a service using a certificate, and to have the service map the client to the an existing account through Active Directory. The following XML shows how to configure the service to map the certificate:

Xml
<behaviors>
  <serviceBehaviors>
    <behavior name="MapToWindowsAccount">
      <serviceCredentials>
        <clientCertificate>
          <authentication mapClientCertificateToWindowsAccount="true" />
        </clientCertificate>
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>

The following code shows how to configure the service.

// Create a binding that sets a certificate as the client credential type.
WSHttpBinding b = new WSHttpBinding();
b.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;

// Create a service host that maps the certificate to a Windows account.
Uri httpUri = new Uri("http://localhost/Calculator");
ServiceHost sh = new ServiceHost(typeof(HelloService), httpUri);
sh.Credentials.ClientCertificate.Authentication.MapClientCertificateToWindowsAccount = true;

Delegation

To delegate to a back-end service, a service must perform Kerberos multi-leg (SSPI without NTLM fallback) or Kerberos direct authentication to the back-end service using the client’s Windows identity. To delegate to a back-end service, create a ChannelFactory and a channel, and then communicate through the channel while impersonating the client. With this form of delegation, the distance at which the back-end service can be located from the front-end service depends on the impersonation level achieved by the front-end service. When the impersonation level is Impersonation, the front-end and back-end services must be running on the same machine. When the impersonation level is Delegation, the front-end and back-end services can be on separate machines or on the same machine. Enabling delegation-level impersonation requires that Windows domain policy be configured to permit delegation. For more information about configuring Active Directory for delegation support, see Enabling Delegated Authentication.

ms730088.note(en-us,VS.90).gifNote:
When a client authenticates to the front-end service using a user name and password that correspond to a Windows account on the back-end service, the front-end service can authenticate to the back-end service by reusing the client’s user name and password. This is a particularly powerful form of identity flow, because passing user name and password to the back-end service enables the back-end service to perform impersonation, but it does not constitute delegation because Kerberos is not used. Active Directory controls on delegation do not apply to user name and password authentication.

Delegation Ability as a Function of Impersonation Level

Impersonation level Service can perform cross-process delegation Service can perform cross-machine delegation

Identification

No

No

Impersonation

Yes

No

Delegation

Yes

Yes

The following code example demonstrates how to use delegation.

Visual Basic
Public Class HelloService
    Implements IHelloService

    <OperationBehavior(Impersonation:=ImpersonationOption.Required)> _
    Public Function Hello(ByVal message As String) As String Implements IHelloService.Hello
        Dim callerWindowsIdentity As WindowsIdentity = ServiceSecurityContext.Current.WindowsIdentity
        If (callerWindowsIdentity Is Nothing) Then
            Throw New InvalidOperationException("The caller cannot be mapped to a Windows identity.")
        End If

        Dim backendServiceAddress As EndpointAddress = New EndpointAddress("http://localhost:8000/ChannelApp")
        ' Any binding that performs Windows authentication of the client can be used.
        Dim channelFactory As ChannelFactory(Of IHelloService) = _
          New ChannelFactory(Of IHelloService)(New NetTcpBinding(), backendServiceAddress)
        Dim channel As IHelloService = channelFactory.CreateChannel()
        Return channel.Hello(message)
    End Function
End Class
C#
public class HelloService : IHelloService
{
    [OperationBehavior(Impersonation = ImpersonationOption.Required)]
    public string Hello(string message)
    {
        WindowsIdentity callerWindowsIdentity = ServiceSecurityContext.Current.WindowsIdentity;
        if (callerWindowsIdentity == null)
        {
            throw new InvalidOperationException
             ("The caller cannot be mapped to a Windows identity.");
        }
        using (callerWindowsIdentity.Impersonate())
        {
            EndpointAddress backendServiceAddress = new EndpointAddress("http://localhost:8000/ChannelApp");
            // Any binding that performs Windows authentication of the client can be used.
            ChannelFactory<IHelloService> channelFactory = new ChannelFactory<IHelloService>(new NetTcpBinding(), backendServiceAddress);
            IHelloService channel = channelFactory.CreateChannel();
            return channel.Hello(message);
        }
    }
}

How to Configure an Application to Use Constrained Delegation

Before you can use constrained delegation, the sender, receiver, and the domain controller must be configured to do so. The following procedure lists the steps that enable constrained delegation. For details about the differences between delegation and constrained delegation, see the portion of Windows Server 2003 Kerberos Extensions that discusses constrained discussion.

  1. On the domain controller, clear the Account is sensitive and cannot be delegated check box for the account under which the client application is running.

  2. On the domain controller, select the Account is trusted for delegation check box for the account under which the client application is running.

  3. On the domain controller, configure the middle tier computer so that it is trusted for delegation, by clicking the Trust computer for delegation option.

  4. On the domain controller, configure the middle tier computer to use constrained delegation, by clicking the Trust this computer for delegation to specified services only option.

For more detailed instructions about configuring constrained delegation, see the following topics on MSDN:

See Also

Tags :


Community Content

k.zambov
Working Security Model using WCF, WPF and Kerberos Security Authentication

In order to architect a system that consists of a few different components spread over multiple servers, there are a few concepts that have to be considered during the analysis phase. Security is a critical piece involved in the architecture, and very often may cause change of plans accordingly. The example below represents the following architecture:

· A Windows 2003 Server (either physical or virtual) with IIS 6 running and a WCF service application attached to the IIS. The WCF application references DLLs from other already developed .NET projects that on their turn access various SQL 2005 Databases on multiple SQL Servers (either physical or virtual). The DLLs can either live in one repository somewhere on the IIS server drives, or can be added to the actual WCF Application as External DLLs and then referenced in the application. The latter is adopted in the example below.
· Finally we have a client application that accesses the WCF service on the IIS server. This application can be anything from Windows Forms, to WPF, to ASP.NET, to Silverlight. In the example below, WPF is used.

Let’s look at the following situation: We want the users to freely use their WPF application without having to login providing a username and password every time they start the app. That means that when a user passes a request to the WCF running on a separate server, they will access this server with their domain user name in active directory. From there, let’s assume that the SQL database on the SQL server in a remote location allows users to login using integrated windows security (which is the most secure way and also allows keeping track of who is doing what on the server at anytime). That also will require the same domain name credentials in active directory so the user is able to access the database for their request.
According to global security standards, the user running a WPF (or any other) application on their workstation, which accesses WCF Service on a server, and then attempts to access a SQL database on a remote server, which is also set to use windows security is not permitted. This type of situation is called double-hoping where the user accesses a server with their domain credentials, but then attempt to access a second server with the same credentials. At this point of time, the user’s credentials will be lost, and the database will be attempted to be accessed with the IIS server’s credentials instead which will typically fail. This is implemented exactly for the purpose to avoid double-hopping.
There are different ways to avoid this situation. One example is setting up the SQL database with a generic username and password. Another is including the IIS server’s credentials to the database permitted users. However using the domain user name from active directory and Windows authentication through the different platforms allows for a better security architecture since no passwords are transferred from one location to the next and since it is easier to monitor users’ activity at all times.
That is why one way to overcome the double-hopping problem is by implementing Kerberos authentication, which is a global security protocol developed at MIT (Massachusetts Institute of Technology) sometime in the 90s and is used widely. This document has examples on how to correctly configure your WCF and WPF applications as well as how to modify some of the IIS settings in order to have a working security model.
Note: In order to create the model, the IIS server has to already be set up with Kerberos authentication. The default server setting for Windows 2003 is NTLM authentication. This part is not covered in the document. Also, the security model will work for users that are already in Active Directory, but not for external users. Third party tools will be necessary to expand this functionality to external logins.

Creating the WCF Service application

Step one of the process is to create a WCF Service Application. Note that the .NET Framework version used in the model is 3.5.
To do so, we need to select the WCF Service Application type in visual studio under the Web projects tab.

From there on, we will have to develop the WCF application like we normally would. We need to create our Service Contract and Data Contract classes in the Public Interface with a default name IService1. The following is the representation of the IService1 code.
<ServiceContract()> _
Public Interface IService1

<OperationContract()> _
Function GetData(ByVal data As MyDataContract) As String

End Interface

<DataContract()> _
Public Class MyDataContract

Private _ClaimObject As Claim_Services.Claim
Private _clmObj As Claim_Services.Claim_DataAccess
Private _currentError As Error

<DataMember()> _
Public Property clmObj() As Claim_DataAccess
Get
Return _clmObj
End Get
Set(ByVal value As Claim_DataAccess)
_clmObj = value
End Set
End Property

<DataMember()> _
Public Property currentError() As Error
Get
Return _currentError
End Get
Set(ByVal value As Error)
_currentError = value
End Set
End Property

<DataMember()> _
Public Property ClaimObject() As Claim
Get
Return _ClaimObject
End Get
Set(ByVal value As Claim)
_ClaimObject = value
End Set
End Property

End Class

Note that the WCF Service Application already has a reference to a DLL (Claim_Services.dll) from an old .NET project that contains a method in one of its classes (the Claim class as the ClaimObject data member above suggests), which will call a SQL database in order to retrieve a record. Our WCF application service is in the position of a middle tier between a client application and other projects’ DLLs that are accessing the database for data manipulation. Its role is to just transport data and requests back and forth like a regular web service.

Once the IService1 is completed, we can move on and implement the service in a regular class that is under the Service1.svc object. This is where most of the security settings for the model need to be created.
In order to be allowed to call the WCF application which will be installed on a Web server by attaching it to IIS, and then call a second server (our SQL Database call in this example), we will have to implement impersonation and delegation along with Kerberos authentication for the purpose. Otherwise, the attempt will result in a double-hop which is not permitted by the Security Standards as explained above.
The following shows the implementation of the GetData Operation Contract from the code above.
<OperationBehavior(Impersonation:=ImpersonationOption.Required)> _
Public Function GetData(ByVal data As MyDataContract) As String Implements IService1.GetData

Try

Dim str As String
Dim securityContext As System.ServiceModel.ServiceSecurityContext = System.ServiceModel.OperationContext.Current.ServiceSecurityContext
Dim ID as Integer = 100

If securityContext IsNot Nothing AndAlso securityContext.WindowsIdentity IsNot Nothing Then

Using securityContext.WindowsIdentity.Impersonate

data.clmObj = New Claim_DataAccess
data.currentError = New Error

str = " getting data- " & data.clmObj.GetOneClaim(ID,data.currentError)
str = str & ": " & securityContext.WindowsIdentity.Name
Return str
End Using
End If

Catch ex As Exception
Return ex.Message
End Try
End Function
Note that the only things that the code does, is instantiate the objects that we need to pass to the GetOneClaim method, and format the string that is returned including the WindowsIdentity.Name object which will show us if we have completed the impersonation process correctly. We will have to see our own domain name coming back from the IIS server if the impersonation is correct once we consume the WCF service with our client application.
In order to start impersonation, we have to decorate the function with the (Impersonation:=ImpersonationOption.Required) statement. The only other thing left is to specify WindowsIdentity.Impersonate in the Security Context while we are making the call to the external DLL and therefore the SQL database. Once this part is completed, there are changes that need to be made in the web.config file of the project. The web.config deals with the type of binding, which is the most critical piece of the model. Everything that we need for the impersonation process is part of the <System.ServiceModel> tag of the configuration. This is an example of what needs to be found there:

<system.serviceModel><diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtTransportLevel="true" />
</diagnostics>

<services>
<service behaviorConfiguration="WcfServiceApplication.Service1Behavior" name="WcfServiceApplication.Service1" >

<endpoint binding="basicHttpBinding" bindingConfiguration="basicBinding" address="" contract="WcfServiceApplication.IService1">
</endpoint>
</service>
</services>

<behaviors>
<serviceBehaviors>
<behavior name="WcfServiceApplication.Service1Behavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<windowsAuthentication includeWindowsGroups="true" allowAnonymousLogons="false"/>
</serviceCredentials>

<serviceAuthorization principalPermissionMode="UseWindowsGroups" />
</behavior>
</serviceBehaviors>
</behaviors>

<bindings>
<basicHttpBinding>
<binding name="basicBinding" maxReceivedMessageSize="2000000" >
<readerQuotas maxArrayLength="2000000" maxStringContentLength="2000000" />
<security mode ="TransportCredentialOnly">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>

There are a few different types of binding that are allowed in WCF. The two that allow for Windows Integrated Security are wsHTTPBinding and basicHTTPBinding. The first one comes by default. However for this example, basicHTTPBinding was used. This one is supposedly less secure, but faster. Note that the type of binding is first specified in the <endpoint binding> tag. Then we need to have a detailed node on binding within the <bindings> tag. This is where we set our security mode to TransportCredentialsOnly and our client Credential type to Windows. In the <behaviors tag>, make sure to set allowAnonymousLogons to False.

Also make sure to locate the <authentication mode="Windows" /> and add the following tag after it:
<identity impersonate="true" />

Deploying WCF in IIS and configuring server properties

At this point, make sure that the Windows server is running .NET Framework 2.0 or above. After setting up the WCF application, the next step will be deploying the WCF application on the IIS server used for the model. This is done simply by copying the folder containing the WCF project to the IIS server. To attach the WCF application to IIS, we have to go through the regular Web Sharing process.
· Find the project folder and go the second root level where the solution (.SLN) file is.
· Right-click on the project folder there and choose Properties.
· In the Properties dialog, select Web Sharing, and then in the Share on: dropdown, select the default choice (usually Default website).
· We can alias the service name or leave it as it is.
· Check Read and Directory browsing under Access permissions and then select Execute (includes scripts) under the Application permissions and click OK.

At this point the WCF service should be attached to IIS and running (assuming IIS is running already). To open the IIS manager, go to Control Panel, Administrative Tools and Internet Information Services Manager. Our service should be running under Web Sites / Default Web Site/ Our service name from above.

Now it is time to make sure that the service settings are configured correct.
· Right-click on the service virtual folder and choose Properties.
· In the Properties window, under the Virtual Directory tab, click Configuration.
· Scroll down in the list of Application extensions and make sure that the .SVC extension is available. If not, click on the Add button.
o To add a new .SVC extension, we need to browse to a particular DLL. This is at: c:\windows\microsoft.net\framework\2.0.50727\aspnet_isapi.dll
o Type .SVC in the extension block and click OK.


· Back in the Properties window, click on the ASP.NET tab. Make sure that version 2.0.50727 or higher is selected for ASP.NET version
· Back on the Properties window, click on the Directory Security tab. Click on Edit under Authentication and access control. Make sure that Enable anonymous access is unchecked, and that Integrated Windows authentication is checked

The last very important step that needs to be performed on the IIS server is to assure that the server is trusted for delegation. This is the setting that will allow the server to pass user’s credentials to remote servers after the WCF impersonation process is completed. This is done from the server’s properties in Active Directory. Under the Delegation tab, make sure that “Trust this computer for delegation to any service (Kerberos only)” is selected.
In order to test if our service is running properly, we open an Internet browser on the server and type in http://localhost followed by the name of our WCF service under the Default Web Site in IIS, followed by the file name ending with .SVC in the service directory.

Creating the WPF client application

The last step of the process is to create the WPF client tester application that will consume the WCF service. In order to do so, after the application itself is created in a regular way, we want to add a Service reference to it which will point to the WCF service. To do, type in the hyperlink in the provided space in the Service Reference dialog box and after the service was found successfully click OK.

By adding the service reference, the app.config for the application will be already configured as supposed to including the type of binding that was earlier specified on the WCF side. This information should be all available in the <client> tag.

In order to configure the WPF completely however, there is a statement that needs to be added in code. When trying to use the service reference to access the WCF service, our code should look like the following:

Using service As ServiceReference1.Service1Client = New ServiceReference1.Service1Client

service.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Delegation

End Using

The TokenImpersonationLevel.Delegation, allows the credentials to be delegated from the IIS server to others. When the application is built, the app.config file should be updated with the following line produced from the code that we just added in the <endpointBehaviors> tag:
<windows allowedImpersonationLevel="Delegation"/>

At this point we should be able to run the WPF application which will consume the WCF service in IIS on a server, which will process certain business logic, impersonate the caller, delegate the credentials further on through Kerberos authentication, and return information to the WPF client eventually.

Tags :

ZowFanTheBarbarian
Great Content Addition k.zambov
Why can't the MSDN articles be this helpful?
Tags :

Nate Garvey
Constrained Delegation
For constrained delegation, what service needs to be added? IIS7 Web Application calls WCF Services hosted in IIS7.
Tags :

Page view tracker