« Marine data and RSS = Safer Boating | Main | California Wildfire Yahoo Pipe »

Facebook Desktop Application Development

I love Adobe AIR and am writing a desktop application using AIR that works with Facebook. One of the challenges of working with Facebook is authenticating your requests to their REST server. Below is some actionscript code that produces an MD5 hash of a Facebook API request. 

Here is the algorithm to be implemented:
 args = array of args to the request, not counting sig, formatted in non-urlencoded arg=val pairs (these are CGI parameters)
 sorted_array = alphabetically_sort_array_by_keys(args);
 request_str = concatenate_in_order(sorted_array);
 signature = md5(concatenate(request_str, secret))

Note that secret is not the Facebook application secret, but the session secret Facebook returns after proper authentication of the user!! There is an actionscript MD5 library (com.gsolo.encryption.MD5) from http://gsolofp.blogspot.com/2006/01/actionscript-3-md5-and-sha1.html that I use. Works great.

 

public static function signRequest(params:Object, secret:String):String
{
   
var hashInput:String = "";
    
//get the keys from the params associative array and add them to a new array
var keys:Array = new Array();
var index:int;

for (var item:String in params)
{
keys[index++] = item;
}
    
//sort the keys
var sorter:Sort = new Sort();
sorter.sort(keys);
 
for (var i:int; i < keys.length; i++)
{
//iterate the sorted keys and concatenate into one big string
trace(keys[i] + "=" + params[keys[i]]);
hashInput += keys[i] + "=" + params[keys[i]];
}

hashInput += secret;

return MD5.encrypt(hashInput);
}


This is not the hard part of signing a request. The bigger challenge is knowing exactly what parameters need to be sent, and that if you are using some special class or library, knowing what it might be sendiing, as well. The Facebook error messages help, but they are undocumented. That's where this blog comes in.

Below is an error response to trying to do a photo upload to Facebook using the built-in upload() method of the File class in AIR. (I did change a few values in it so the signature won't compute.)

Details:
<error_response xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <error_code>104</error_code>
  <error_msg>Incorrect signature</error_msg>
  <request_args list="true">
    <arg>
      <key>Filename</key>
      <value>kids.jpg</value>
    </arg>
    <arg>
      <key>call_id</key>
      <value>1215090174125</value>
    </arg>
    <arg>
      <key>method</key>
      <value>facebook.photos.upload</value>
    </arg>
    <arg>
      <key>api_key</key>
      <value>281b9cd2f09c077b2bb100707de</value>
    </arg>
    <arg>
      <key>session_key</key>
      <value>f6bec46c8aa0647b3f377b4440679</value>
    </arg>
    <arg>
      <key>v</key>
      <value>1.0</value>
    </arg>
    <arg>
      <key>sig</key>
      <value>6949810fb9aff86b103520760ff8</value>
    </arg>
    <arg>
      <key>Upload</key>
      <value>Submit Query</value>
    </arg>
  </request_args>
</error_response>

What's significant about this message is that it actually is telling you everything that Facebook is using to compute the signature for the request it received. The keys and values are what it recevied from your computer. Put them into the method above (except for sig, of course), and you get the signature that Facebook computed when it attempted to authenticate your request. This looks straight forward, except that the Filename and Upload arguments are not provided directly by you- they are actually being put into the request by File.upload(). Nor are they mentioned as being required parts of the request in the Facebook API, and in fact, neither Filename nor Upload are used by Facebook. But since they are sent, they are part of the request that Facebook uses to compute the signature and if the signature you send does not match theirs, your request fails.

The moral of the story is you need to know what you are really sending when doing any type of hash of CGI parameters. this affects Facebook, Amazon, and others.

TrackBack

TrackBack URL for this entry:
http://www.erichizdepski.com/blog-mt1/mt-tb.fcgi/51


Hosting by Yahoo!

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)