Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

Here is my scenario: I have a SharePoint site I am working on, and it is on one server farm. In this site, I have created an HttpHandler that uses a SharePoint search webservice that is located on a different server. So that looks something like this:

  1. SharePoint Server A, where my site lives
    • Has a service reference to SharePoint search web service on Server B
    • Has an http handler that uses the service reference to call the search service
  2. SharePoint Server B, where the search service lives

My code looks like this:

BasicHttpBinding binding = new BasicHttpBinding();

binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;

QueryServiceSoapClient _queryService = new QueryServiceSoapClient(binding, new EndpointAddress("http://easearch.ea.com/_vti_bin/search.asmx"));
_queryService.ClientCredentials.Windows.AllowNtlm = true;
_queryService.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
_queryService.ClientCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
//_queryService.ClientCredentials.Windows.ClientCredential = new NetworkCredential("MyUsername", "MyPassword", "MyDomain"); //This is the only way it seems to work
//NetworkCredential userCredential = CredentialCache.DefaultCredentials.GetCredential(_queryService.Endpoint.ListenUri, "NTLM");
//_queryService.ClientCredentials.Windows.ClientCredential = userCredential;

string status = _queryService.Status();

If I use this code from a console application on my dev box, it works as expected. But when I try to use the same code from my http handler, it gives the error

The HTTP request is unauthorized with client authentication scheme 'Ntlm'. The authentication header received from the server was 'NTLM'.

I've tried a number of different combinations of the code above and the only one that works from my HttpHandler is when I directly provide my credentials. Anyone have any ideas?

Thanks.

share|improve this question
add comment

2 Answers

up vote 0 down vote accepted

You are encountering the NTLM double hop issue here. NTLM/Windows Authentication can only pass credentials from one machine to the next, but no further.

The best solution is to implement Kerberos in your environment. This will fix all these issues (and should always be configured before deploying SharePoint IMHO). Then you will need to set HttpClientCredentialType to Windows instead of Ntlm.

The only other option is to specify credentials - either explicitly as you are or by elevating permissions as Muhimbi describe.

share|improve this answer
add comment

From what security context is the code being invoked? If you are elevating the privileges of the calling code then the credentials of the client application pool will be used. This user will need to have the proper privileges on the 2nd farm's search web service.

Here is some code I use for similar scenarios. There is a wrapper around it (not included below) that elevates privileges to the identity the App pool is running under.

BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

// ** We need to specify an identity (any identity) in order to get it past .net3.5 sp1
EndpointIdentity epi = EndpointIdentity.CreateUpnIdentity("unknown");
EndpointAddress epa = new EndpointAddress(new Uri(address),epi);

client = new DocumentConverterServiceClient(binding, epa);

client.Open();

Hope this helps.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.