I was working with a web service client that talked to SharePoint this week. I wrote a quick Silverlight app that extracted a list of tasks out of a SharePoint list. I love how simple this is to tap into:
The previous URL will show the path to one of the web services provided out-of-the-box by SharePoint. This particular web service provides several methods for dealing with SharePoint lists. I just needed to call the GetListItems() method and pass in the list name and view name as parameters in order to get my data.
This worked fine on my local machine, but when I migrated the solution to a staging server, the SharePoint web service refused to send me the data. After a bit of finagling, I realized the web service was happy to talk to my laptop, but it politely declined the remote web server's request as I lacked the proper credentials. I even was running the web solution with impersonation enabled because I wanted to pass along my Windows credentials during the call from the web server to the remote SharePoint server. I forgot that this is just simply not possible.
For security reasons, the web server does not hold on to my credentials "just in case" I might want to use them later. In this scenario, I do need them - but no dice. This particular list in SharePoint is locked down tight.
I didn't have the proper credentials when my web service client fired off a request to SharePoint. When I was running on my local machine, using Casinni, my credentials were readily available. On a remote web server, the credentials vanish. This is called a "Double Hop" problem - the hops are from the browser, to the web server, to another remote web server. The second hop tanked. It was a silly mistake on my part, but hopefully by writing this down now will help me remember sooner next time.
The code below shows how I solve this problem by manufacturing a credential on-the-fly and then fire off a request to SharePoint. There are multiple ways of solving this problem; I just happened to chose this one.
MySharePoint.Lists list = new ProjectBoard.MySharePoint.Lists();
list.Credentials = new System.Net.NetworkCredential(
XmlNode listItemsNode = list.GetListItems(
null, null, "100", null, null);
XmlNode dataNode = listItemsNode.ChildNodes;
foreach (XmlNode rowNode in dataNode.ChildNodes)
// extract values here
Now that I've got this little prototype functional, I can encrypt the credentials in the web.config file by using DPAPI, an encryption tool that makes it easy to protect sensitive information. Since I'm creating new credentials here, I can avoid the Double Hop problem and get on with my prototype.