The Problem
When calling WSS / SharePoint web services (such as Lists.asmx) via WCF, you will normally get this error if you leave the settings as configured by the “Add Service Reference Wizard” :
“The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'NTLM'.”
The Solution
You must specify a non-anonymous impersonation level for your ClientCredentials. Just specifying a username and password for your WCF Service reference's ClientCredentials.UserName.UserName and ClientCredentials.UserName.Password is not sufficient to resolve the problem.
In particular (When SharePoint server is on different domain):
ServiceReference1.ListsSoapClient client = new ServiceReference1.ListsSoapClient();
client.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential("username", "password", "domain");
client.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Identification;
client.GetListCollection();
Of course, when on same domain, don’t have to pass in the Windows.ClientCredential information. You can also set the above values in app.config configuration elements rather than code, but I won't cover that here.
You can use (with descending levels of security):
System.Security.Principal.TokenImpersonationLevel.Identification
System.Security.Principal.TokenImpersonationLevel.Impersonation
System.Security.Principal.TokenImpersonationLevel.Delegation
Details on these impersonation levels can be found at: http://msdn.microsoft.com/en-us/library/system.security.principal.tokenimpersonationlevel.aspx
Config Changes
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="ListsSoap">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
<client>
<endpoint address="http://servername/_vti_bin/Lists.asmx"
binding="basicHttpBinding" bindingConfiguration="ListsSoap"
contract="ServiceReference1.ListsSoap" name="ListsSoap1" />
</client>
</system.serviceModel>
</configuration>