With Integrated Authentication its fairly often that people find themselves in a situation where the currently logged in users credentials are not passed from the client to a SQL server / File share / some other server that they are trying to access from SPS. I bumped into it myself and was tearing my hair apart till my colleague Walter Warren told me what the "Double-Hop Issue" was.
Though I’ve titled this blog under SharePoint this actually applies to ASP.NET as well. The problem I faced was that i was creating an ASP.NET web page that consumes the SharePoint Search web service. The ASP.NET app was hosted on a different IIS machine than SPS. The ASP.NET application had Integrated Windows Authentication turned on. All was fine when I was testing the ASP.NET page right from the server where IIS was running, however, when I tried running the same page from another workstation - I kept getting 401 - Unauthorized access errors.
This problem is due to Integrated Windows Authentication that’s turned on in IIS for the ASP.NET application virtual directory. The issue is known as the "Double Hop" issue - when we use Integrated Security, the user credentials are passed from the client system (in this case the different station) to the server that’s running IIS (in this case the ASP.NET application). When the IIS running the ASP.NET app makes a request to the SharePoint server (a second hop) it cannot pass the user credentials passed from the client system. This is a little known documented limitation in IIS, you can refer to a KB on http://support.microsoft.com/default.aspx?scid=kb;en-us;264921 (check the limitations section under Windows NT Challenge/Response - Integrated Windows Authentication was formerly named NTLM, or Windows NT Challenge/Response authentication).
There are 3 ways to workaround this problem
1) Turn of Windows Integrated Authentication and turn on Basic Authentication
2) Hardcode the credentials passed to SharePoint in the ASP.NET application code
3) Turn on Kerbrose Authentication
Option 1) Turn of Windows Integrated Authentication and turn on Basic Authentication
You can turn off Integrated Authentication and turn on Basic Authentication on the virtual directory running the ASP.NET application. With this you should be prompted for your user name and password every time you try to access the ASP.NET application and unlike Integrated Windows Authentication - your credentials are passed even in the second hop.
Note that the drawbacks of this option are
i) in Basic Authentication the user credentials are passed as clear text
ii) users will get a pop-up asking for user credentials every time they try to access your page.
Option 2) Pass user credentials using code
My code used the default credentials from the credential cache - however you can hardcode the credentials that are passed to SharePoint. In the SPS web service case i had to create a NetworkCredential object with the user credentials hardcoded and set the object to the Credentials property of the QueryService proxy object.
Changed the line from
qs.Credentials = System.Net.CredentialCache.DefaultCredentials;
qs.Credentials = new System.Net.NetworkCredential("<User Name", "<Password>", "<Domain Name>");
In the case of a Fileshare, etc - you will need to use an unmanaged API to impersonate the user on the SPS machine, here is an MSDN article to do that http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemSecurityPrincipalWindowsIdentityClassImpersonateTopic.asp
You can alternatively instead of hardcoding the credentials in code - you can put them in the Web.Config file and retrieve at run time. If you do this - you should also encrypt the password.
Option 3) Turn on Kerberos Authentication
You need to turn on Kerberos on IIS and configure SharePoint for this - you can refer to this KB article for the exact steps http://support.microsoft.com/?id=832769
Any of these three options should resolve the problem.