The HTTP request is unauthorized with client authentication scheme 'Ntlm'

It's a long time since the question was posted, but I experienced the same issue in a similar scenario. I have a console application and I was consuming a web service and our IIS server where the webservice was placed has windows authentication (NTLM) enabled.

I followed this link and that fixed my problem. Here's the sample code for App.config:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="Service1Soap">
                <security mode="TransportCredentialOnly">
                    <transport clientCredentialType="Ntlm" proxyCredentialType="None"
                        realm=""/>
                    <message clientCredentialType="UserName" algorithmSuite="Default"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost/servicename/service1.asmx" 
            binding="basicHttpBinding" bindingConfiguration="ListsSoap"/>
    </client>
</system.serviceModel>

OK, here are the things that come into mind:

  • Your WCF service presumably running on IIS must be running under the security context that has the privilege that calls the Web Service. You need to make sure in the app pool with a user that is a domain user - ideally a dedicated user.
  • You can not use impersonation to use user's security token to pass back to ASMX using impersonation since my WCF web service calls another ASMX web service, installed on a **different** web server
  • Try changing Ntlm to Windows and test again.

OK, a few words on impersonation. Basically it is a known issue that you cannot use the impersonation tokens that you got to one server, to pass to another server. The reason seems to be that the token is a kind of a hash using user's password and valid for the machine generated from so it cannot be used from the middle server.


UPDATE

Delegation is possible under WCF (i.e. forwarding impersonation from a server to another server). Look at this topic here.


For me the solution was besides using "Ntlm" as credential type, similar as Jeroen K's solution. If I had the permission level I would plus on his post, but let me post my whole code here, which will support both Windows and other credential types like basic auth:

    XxxSoapClient xxxClient = new XxxSoapClient();
    ApplyCredentials(userName, password, xxxClient.ClientCredentials);

    private static void ApplyCredentials(string userName, string password, ClientCredentials clientCredentials)
    {
        clientCredentials.UserName.UserName = userName;
        clientCredentials.UserName.Password = password;
        clientCredentials.Windows.ClientCredential.UserName = userName;
        clientCredentials.Windows.ClientCredential.Password = password;
        clientCredentials.Windows.AllowNtlm = true;
        clientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
    }  

I had to move domain, username, password from

client.ClientCredentials.UserName.UserName = domain + "\\" + username; client.ClientCredentials.UserName.Password = password

to

client.ClientCredentials.Windows.ClientCredential.UserName = username; client.ClientCredentials.Windows.ClientCredential.Password = password; client.ClientCredentials.Windows.ClientCredential.Domain = domain;