WCF Impersonation for Hosted Services
In my blog entry “ASP.NET Compatibility Mode”, I showed how to perform impersonation with ASP.NET. WCF provides more flexible service operation level impersonation. Here is a common question that I heard:
Question:
How can I use WCF impersonation for hosted services with BasicHttpBinding?
Answer:
You can use different security modes (specified in BasicHttpSecurityMode) to achieve this:
- Message
- Transport
- TransportCredentialOnly
- TransportWithMessageCredential
Here I will just show how to use “TransportCredentialOnly” mode which needs special treatment for hosted case.
Step 1: Implement the operation
In order to enable impersonation, you need to specify the impersonation option on your service operation. Here is a simple service contract:
[ServiceContract]
interface IHelloService
{
[OperationContract]
string Hello(string text);
}
To enable impersonation for the operation “Hello”, you need to specify the Impersonation property for the OperationBehavior attribute in the operation implementation as following:
[OperationBehavior(Impersonation=ImpersonationOption.Required)]
public string Hello(string text)
{
return string.Format("Hi {0}, you said: {1}", WindowsIdentity.GetCurrent().Name, text);
}
Step 2: Create the binding
To specify the security mode to “TransportCredentialOnly”, there are different types of authentication types that we can use. The most common secure type is “Windows” which means that the underlying transport will use Kerberos (or NTLM if Kerberos is not supported) negotiation. Here is a sample configuration section:
<basicHttpBinding>
<binding name="MyAuthBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpBinding>
Step 3: Configure the virtual application in IIS
Now that we have WCF service implementation and binding settings, we need to configure IIS to host the service correctly. Here are the steps:
- Create a virtual application called “sample” in IIS to host your service.
- Ensure to turn on “Integrated Windows authentication” for this virtual application. This will allow IIS to use Kerberos to perform authentication. Specifying a different scheme will cause WCF service activation error.
At this point, you have the hosted WCF service ready to handle requests.
Step 4: Create a client
Now we can create a simple client to connect to the above service. Here is the binding that matches the one on the service-side:
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
With this binding, we can easily create a proxy to connect to the service:
ChannelFactory<IHelloService> factory = new ChannelFactory<IHelloService>(
binding, new EndpointAddress("https://localhost/sample/service.svc"));
IHelloService proxy = factory.CreateChannel();
Console.WriteLine(proxy.Hello("Hi"));
((IChannel)proxy).Close();
factory.Close();
The sample code is attached.
Comments
Anonymous
January 10, 2008
In this example the WCF service is hosted on IIS, how would I go about if the WCF service is hosted on a console app?Anonymous
September 19, 2011
Hi if the user is outside of domain, it is getting error, the error is that - >>>>> The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate,NTLM'. ---> System.Net.WebException: The remote server returned an error: (401) Unauthorized. >>>> Thanks.Anonymous
November 27, 2012
Thanks very much. This was more than helpful.