How to Validate a Facebook Canvas Page

Facebook has good documentation on how to authenticate a request to your canvas page.  You can find that documentation here.

However, if you’re developing your page in ASP.NET (WebForms or MVC), there’s a few things in the documentation that may throw you off.  The remainder of this post assumes you’re developing a Facebook application in ASP.NET MVC and your Facebook application is set as iFrame (for authentication).

When your application is set as iFrame, the Facebook parameters are contained in the request parameters (and not in cookies as you may be lead to believe from the use of the keyword in the documentation).  The purpose of validating a canvas page, is to ensure that the request IS coming from Facebook.  Therefore, Facebook has computed a hash value (called a signature) with all the (Facebook) parameters + your application’s secret key.  So, in order to verify, you just have to perform the same computation and compare your computed signature with Facebook’s.  This works because only you and Facebook should know your application’s secret key.

Here’s a snippet of code that you can use to perform that verification:

public static bool IsRequestValid(string applicationSecretKey, HttpRequestBase request)
    bool valid = false;

    string originalSignature = request.Params["fb_sig"];
    if (!string.IsNullOrWhiteSpace(originalSignature))
        // Step 1:  Generate an input string
        // i    -   Order all "facebook" parameters alphabetically
        // ii   -   Remove the preceeding 'fb_sig_' characters
        // iii  -   Concantenate them all
        string input = string.Join("", from p in request.Params.Cast<string>()
                                        where p.StartsWith("fb_sig_")
                                        orderby p ascending
                                        select p.Remove(0, 7) + "=" + request.Params[p]);

        // Step 2:  Append the application's secret key
        input += applicationSecretKey;

        // Step 3:  Compute a signature  
        // i    -   Compute an MD5 hash with the generated string
        // ii   -   Convert the hash into hexadecimal and concantenate them
        var data = HashAlgorithm.Create("MD5").ComputeHash(Encoding.ASCII.GetBytes(input));
        string computedSignature = string.Join("", from d in data
                                                    select d.ToString("x2"));

        // Step 4: Compare with the orignal signature
        if (computedSignature == originalSignature)
            valid = true;

    return valid;

This uses LINQ quite heavily and also uses String.Join in favor of String.Concat or StringBuilder because of the reported performance advantage the Join method has over the other ones.

Happy Coding!