Search code examples
c#wcfwindows-authenticationwsdualhttpbinding

Share windows identity between WCF services with WSDualHttpBinding


I have two WCF services hosted separately in IIS 7. The first service is callable from outside and uses a WebHttpBinding with windows authentication. The second service is only called by the first one, using a WsDualHttpBinding.

When the first service is called, I can get the user's windows name from ServiceSecurityContext.Current.WindowsIdentity.Name. In the second service, that doesn't work and ServiceSecurityContext.Current.WindowsIdentity.Name is just IIS APPPOOL\DefaultAppPool.

I configured the WsDualHttpBinding to use windows authentication, but that didn't help. Here is the server-side configuration:

<wsDualHttpBinding>
  <binding name="internalHttpBinding">
    <security mode="Message">
      <message clientCredentialType="Windows"/>
    </security>
  </binding>
</wsDualHttpBinding>

And here's the code in the first service to establish communication with the second service:

private WSDualHttpBinding binding = new WSDualHttpBinding();
private ChannelFactory<IMyService> factory;
public IMyService Contract { get; set; }
public MyServiceCallback Callback { get; set; }

public MyService(Uri uri)
{
    EndpointAddress address = new EndpointAddress(uri);
    Callback = new MyServiceCallback();
    var instanceContext = new InstanceContext(Callback);

    binding.Security.Mode = WSDualHttpSecurityMode.Message;
    binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;

    factory = new DuplexChannelFactory<IMyService>(instanceContext, binding, address);
    factory.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
    factory.Credentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
    Contract = factory.CreateChannel();

    // Call operations on Contract
}

How can I configure the first service to pass on the user's identity to the second service?


Solution

  • This seems to be a problem with pass-through authentication. First, you need to be in a Active Directory environment. Kerberos must be used for authentication, NTLM will not work. You can use klist to check this: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/klist

    Also see https://blogs.msdn.microsoft.com/besidethepoint/2010/05/08/double-hop-authentication-why-ntlm-fails-and-kerberos-works/ for an explanation.

    May be this SO article can help:

    Pass Windows credentials to remote https WCF service

    And this: https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/delegation-and-impersonation-with-wcf