6

I am unable to successfully call a WCF service with NTLM authentication from .NET Core running on a linux box (docker container). The same code works perfectly on Windows 10 though.

What I have done:

  • Add this to ConfigureServices:
AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
  • Run apt-get -y install gss-ntlmssp
  • This is the code prior to calling the service:
var client = new WcfServiceSoapClient();
client.Endpoint.Address = new EndpointAddress(settings.Uri);
client.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
client.ClientCredentials.Windows.ClientCredential = new NetworkCredential
{
    Domain = settings.Domain,
    UserName = settings.Username,
    Password = settings.Password
};
var binding = (BasicHttpBinding)client.Endpoint.Binding;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.Ntlm;

As mentioned this works fine on Windows 10. On Linux the following error is logged:

System.ServiceModel.Security.MessageSecurityException: The HTTP request is unauthorized with client authentication scheme 'Ntlm'. The authentication header received from the server was 'NTLM, Negotiate'.
   at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass1_0.<CreateGenericTask>b__0(IAsyncResult asyncResult)

Question is: why is it still failing on linux?

kipusoep
  • 2,174
  • 6
  • 24
  • 34
  • Which binding the server uses, do you generate the client proxy class by using Microsoft wcf web service reference provider? Do you have try to use ChannelFactory to Call the service? https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-use-the-channelfactory – Abraham Qian May 16 '19 at 10:25
  • @AbrahamQian I used a generated WSDL file inside VS2019 when adding a Connected Service, which was handed to me by the developer of the WCF Service. I'm not using the ChannelFactory, because I don't have an interface generated by the VS WCF tool. – kipusoep May 16 '19 at 14:08
  • I managed to use the ChannelFactory (didn't see the interface because of the lack of an 'I' suffix), but I'm getting the same error on Linux: `System.ServiceModel.Security.MessageSecurityException: The HTTP request is unauthorized with client authentication scheme 'Ntlm'. The authentication header received from the server was 'NTLM, Negotiate'.` – kipusoep May 16 '19 at 14:22
  • In the end we switched to Basic authentication. [This issue should be fixed in .NET Core 3](https://github.com/dotnet/corefx/issues/34879#issuecomment-496516869). – kipusoep May 28 '19 at 13:33

2 Answers2

3

I had the same problem and was able to fix it, with a lot of help from the guys on the net core GitHub.

Essentially net core uses the underlying OS to handle http calls. Before, on Linux libCurl was used, but the newer SocketsHttpHandler uses gss, which doesn't come with ntlm support (at least not in the 'microsoft/dotnet:2.2-aspnetcore-runtime-stretch-slim' image).

To fix this you need to install an extra library in your container, using the docker file. Right after

FROM microsoft/dotnet:2.2-aspnetcore-runtime-stretch-slim

(Or whatever image you use)

on the next line add the following:

RUN apt-get update && apt-get install -y --no-install-recommends apt-utils gss-ntlmssp

Hope this helps!

  • No unfortunately not. I already had tried this but didn't make a difference. – kipusoep Jul 18 '19 at 13:21
  • I just noticed you set AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false) and you also add the gss-ntlmssp package. This seems odd as gss-ntlmssp is necessary for GSSAPI to use ntlm authentication, but switching SocketsHttpHandler off enables CurlHandler which uses LibCurl and not GSSAPI... – Stephan Ghequiere Jul 18 '19 at 13:30
1

I found that if we remove Negotiate provider in the Windows Authentication on the server side the project will work, no matter which way of invocation.
enter image description here
It seems that Netframework will auto-negotiate the way of authentication, Core cannot, which ought to be a bug.
Feel free to let me know if there is anything I can help with.

Abraham Qian
  • 7,117
  • 1
  • 8
  • 22
  • Thanks for you reply. I've read somewhere that removing Negotiate (or even having NTLM come first) fixes everything, but unfortunately this didn't work in our case. – kipusoep May 17 '19 at 12:05
  • On my side, only removing the Negotiate provider could make it work. It seems that we should ensure the authentication header is identical on both sides. – Abraham Qian May 20 '19 at 03:19
  • I asked the other party (which is hosting the WCF service) if this was the way they removed the Negotiate header and they confirmed it. So for some unknown reason it's still not working. – kipusoep May 20 '19 at 14:00
  • This did not work for us either. I am trying to figure out a way to set this at runtime so that I am not changing a generated file. – jeffkenn Jan 25 '22 at 14:38