Wednesday, June 1, 2011

Fixing Authentication Errors From The SlideShare API’s HTTP POST Methods

Chris Domino, Director, Enterprise Architect

For those of you who read me regularly, you are aware of my aversion to third party components, rouge APIs, open source code, etc. It's not that I necessarily believe that they are bad, or that I feel I could always do a better job building it myself from scratch. Instead, the reason the hair on the back of my neck stands up whenever I need to make a decision on including someone else's code in my project is because if it breaks, I can't fix it.

Pure and simple: if I wrote it, and it breaks, well, at least i know it is within my ability to fix it.

Of course if someone else has already solved the problem, I'd rather spend my time attacking something new than solving that particular problem better.

In my current project, we have an integration point with SlideShare, an online PowerPoint collaboration site. Think Flickr for presentations. SlideShare has a RESTful API that lets you authenticate to the site, and provides CRUD operations to facilitate basic document management. I was all set to write a .NET data access class to wrap the WebRequests needed to interact with the API in a more OO-ish manner when a colleague found that someone had already written one.

Even though it's hosted on SlideShare's site, it has one of those "use at your own risk" disclaimers. Apparently, all the wrappers for their REST API were built by contributors, not internally by SlideShare. (Cue the hair on the back of my neck...) However, instead of ranting about using unreliable open source code, I quietly downloaded the binaries and kicked the tires.

The first thing I noticed is that the DLL is not signed, and since this was a SharePoint 2010 farm solution, all of our assemblies had to be GACed. So we definitely needed to pull down the full source code, add it as a project to our solution, sign it, and recompile it ourselves. That made SharePoint happy, and within minutes we were uploading presentations to SlideShare. Kind of...

The other social media integration points for this app are Flickr and YouTube, which are much more professional APIs. For example, in both, there is an overload to their respective upload methods that takes in a Stream, which is pretty natural when dealing with files. The only gotcha here is that you have to instruct .NET to trust any certificates provided by the target site that your browser normally takes care of. Simply add the following line of code before your call to the third party API:

  1. //HACK: trust SSL implicitly
  2. ServicePointManager.ServerCertificateValidationCallback = (_, __, ___, ____) => { return true; };

Basically, this code says: "I don't care what you send me; I trust you." Do not do this with lesser-known target sites!

The SlideShare API supports uploading from a byte array, which is not a far jump from a stream (SPFiles in SharePoint actually can give you either), but it doesn't seem to work. The overload that takes in the array does an HTTP POST behind the scenes. However, any POST made to SlideShare fails with the following response:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <SlideShareServiceError>
  3. <Message>
  4. 2: Failed User authentication
  5. </Message>
  6. </SlideShareServiceError>


Now of course, the API wrapper passes the raw XML responses through, so I had to feed these into XMLDocuments myself and extract the error messages. And since each different response has a different root node value, I couldn't create a base error class and serialize it cleanly. Boo.


So instead, we used the overload that took in a URL (instead of a byte array) that does a GET behind the scenes (instead of a POST) and it worked. The problem is that, of course, this URL has to be publically accessible so SlideShare can pull it up. This makes working in a development environment annoying, since they are not generally public facing.

We ran into this issue again with the DeleteSlideshow method: passing in the same credentials and using the same API key as the GET methods that worked resulted in these failures. Reading the SlideShare documentation says that the method uses an HTTP GET. However, the .NET API uses a POST. So perhaps the above error message makes sense, but it certainly leads you down the wrong path.

The solution? Well, do a GET instead! Of course there are security risks using HTTP GETs to do DELETEs if you aren't careful, so, you know, be careful. I'm surprised the SlideShare REST API doesn't address this. (But since it's not my code, I can't fix it!) To tweak the .NET wrapper, navigate to the "DeleteSlideshow" method (in SlideShare.cs) and change the last line to use "GetCommand" instead of "PostCommand."

All that said, I still feel I lucked out with this API; things could have been a lot messier. The lesson learned is that if a site provides .NET API's, they should be POC-ed (proof-of-concept-ed) out before declaring victory. However, I'm going to start operating with the attitude that third party code should be considered innocent until proven guilty.