Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dotnet core web api running inside docker fails to authenticate when consuming external WCF service

I'm building a RESTful API using dotnet core 1.1.2.

A big part of this api requires making requests to an external WCF service. These requests are authenticated using windows-based authentication with username, password and domain.

I'm currently in the process of making the api production ready and I wanted to try dockerizing it.

The problem I'm having is that authentication fails towards this third party WCF service as soon as it's called from within the docker container. Running the API using the dotnet runtime works from both windows and mac and the service gets authenticated as it should.

I consume the WCF service using the Connect wcf service feature of Visual studio 2017 and then modifying the endpoint binding with the correct authentication mode.

public ServiceSoapClient(EndpointConfiguration endpointConfiguration, string username, string password, string domain) :
base(ServiceSoapClient.GetBindingForEndpoint(endpointConfiguration), ServiceSoapClient.GetEndpointAddress(endpointConfiguration))
{
    this.ChannelFactory.Credentials.Windows.ClientCredential.UserName = username;
    this.ChannelFactory.Credentials.Windows.ClientCredential.Password = password;
    this.ChannelFactory.Credentials.Windows.ClientCredential.Domain = domain;

    this.Endpoint.Name = endpointConfiguration.ToString();
    ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
}

private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
{
    if ((endpointConfiguration == EndpointConfiguration.ServiceSoap))
    {
        System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
        result.MaxBufferSize = int.MaxValue;
        result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
        result.MaxReceivedMessageSize = int.MaxValue;
        result.AllowCookies = true;
        result.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.Transport;
        result.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
        return result;
    }
    throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
}

I've tried both Ntml and Windows as ClientCredentialType.

I've verified that the authentication credentials don't get messed up when transferring the api to the docker container by hard coding the credentials inside the app, then running it using the normal dotnet runtime to verify that it works. Finally building the docker image with exactly the same published app and running it again. When exactly the same app is running inside docker it fails to authenticate.

The output from the application is:

The HTTP request is unauthorized with client authentication scheme ‘Negotiate’. The authentication header received from the server was ‘Negotiate, NTLM’.

Which is the same output as if when I'm using incorrect credentials.

I'm wondering if this could be somehow related to how networking works with docker and if the api can't negotiate with the WCF service since it's bridging through the docker host.

If anyone more knowledgeable with docker or WCF consumtion inside dotnet core might have some insight it would be very helpful.

Best regards, Linus.

like image 849
Linus Eiderström Swahn Avatar asked Sep 18 '17 13:09

Linus Eiderström Swahn


1 Answers

For anyone experiencing the same issue this is due to the way kerberos is configured on non-windows platforms. This has nothing to do with docker per say but rather running as a linux-based container.

The solution is to either switch your platform to windows or correctly configure kerberos authentication on your platform. This is discussed in more detail in the following github issues:

https://github.com/dotnet/wcf/issues/2641 and https://github.com/dotnet/corefx/issues/9533

like image 142
Linus Eiderström Swahn Avatar answered Sep 22 '22 17:09

Linus Eiderström Swahn