Sl.ayer's lair

It looks like you're writing a blog...

For quite some time now, .NET developers have been left out in the cold without official support from Facebook. No more, my friends! Today, Andrey Goder announced the first release of Facebook’s official C# SDK in his blog post. For many of us, this raises the following questions: what does it mean for all the unofficial .Net SDKs floating around? Do I keep using my own Facebook library or should I switch to the official SDK?

The decisive factor in answering this question for all Silverlight developers is, of course, Silverlight support. Based on the first look, the official SDK is not Silverlight ready, although it should be easy enough to add support for an asynchronous communication model.

Also, Facebook SDK is quite similar to GraphLight, in that neither provides any help with Facebook authentication. All in all, the alpha state of the first official .Net SDK is pretty obvious. For now, I will stick with my own GraphLight, but I will keep an eye on the Facebook SDK to see how its Silverlight support progresses.


In my previous post about the GraphLight library, I mentioned that the first step in using the library is to supply it with an access token. What I conveniently skimmed over is the explanation of what an access token is and how does one get a hold of it.  I did this because answering those questions isn’t simple, and would benefit from dedicated elaboration.

According to Facebook: “An access token allows an application to perform authorized requests on behalf of the user by including the access token in Graph API requests.” You can read about the process of obtaining an access token on the Facebook Developers Site. Although Facebook documentation provides a good starting point, it does not account for peculiarities of Silverlight. In this post, I will go over issues I encountered while implementing Facebook authentication in a Silverlight OOB application, and offer my solutions.

Facebook documentation outlines two main flows of authentication available to applications:  The first method utilizes sequence of redirects to Facebook site and back; the second method uses single sign-on with the JavaScript SDK. Of the two, only the former method can be used in a Silverlight OOB application due to restrictions on access to the hosting page’s DOM. Upon closer examination, the Desktop Application Authentication process emerges as the most obvious choice for an OOB application.

Implementing a desktop authentication flow in accordance with Facebook documentation is quite straightforward:

  1. Create WebBrowser control in code or in XAML
  2. Navigate to https://graph.facebook.com/oauth/authorize
  3. Intercept the redirect to login_succes.html using LoadCompleted event and read the access token out of the URL

Problem #1

WebBrowser control needs Full-Trust to show pages from sites other then application’s origin. Because the Facebook authentication process requires redirect to facebook.com, the OOB application must be in full-trust mode! After many different attempts to find an acceptable workaround for standard OOB applications, I came to the conclusion that although it can be done, the resulting user experience is so poor that it is simply not worth it.

Resolution: Configure application to require Full-Trust.

Problem #2

Using the LoadCompleted event to intercept the redirect to login_succes.html doesn’t work because the Uri property of NavigationEventArgs is always null. If one is unable to read the access token out of the URL, using the Desktop Application Authentication process is no longer an option.

Resolution: An alternative approach comes in the form of an authentication flow recommended for Web Applications and Mobile Applications. Web application authentication uses a two-step process, with the first step similar to that of desktop authentication, but instead of an access token, it returns code that can be exchanged for an access token in a separate step.

In order to detect redirects and pass code to the Silverlight application, following steps need to be taken:

1. Create success.html page

<html>
  <head>
   <title>Facebook Login Callback</title>
   <script type="text/javascript">
      window.external.notify(window.location.href);
   </script>
  </head>
  <body />
</html>

2. Success page should be hosted on the same domain as the application and its url should start with Connect URL (see Facebook connect settings). Both conditions are sine quibus non.

3. Point redirect_uri parameter to the location of the success page

4. Add ScriptNotify handler to WebBrowser control:

  browser.ScriptNotify += (a, b) =>
  {
     int n = b.Value.IndexOf("?code=");
     if (n > 0)
     {
         //extract code from b.Value
         //exchange code for access token as described in Facebook documentation
         WebClient wc = new WebClient();
         wc.DownloadStringAsync(new Uri(
              string.Format(token_xchange, app_id, redirect_url, secret, code)));
         wc.DownloadStringCompleted += (c, d) =>
         {
             //extract access token from d.Result
             LoginSuccess(access_token);
         };
     }
     else
     {
         if (b.Value.IndexOf("user_denied") > 0)
         {
             LoginFailed();
         }
     }
  };

At last a bit of good news: The method described above actually works, but…

Problem #3

Doing a token exchange from a Silverlight application requires a secret key to be stored inside of the package redistributed to the end users, which is inherently not secure.

Resolution: Replace success.html with success.aspx or success.php or any other technology that allows one to execute code server-side. Perform token exchange on the server and simply pass the access token to ScriptNotify handler.

In an attempt to find a simpler solution, I found a post on the Facebook developers forums showing a way to get an access token in one step, without going through a token exchange. Unfortunately, that method relies on undocumented features and looks kind of “hacky,” so I am not going to present it here.

Postmortem

Implementing Facebook authentication in an OOB silverlight application turned out to be a challenge. Most of the issues I encountered were related to limitations of the WebBrowser control. Some security restrictions were expected and quite reasonable, while others appear to be to overreaching. It would be nice to see Microsoft considering use cases for Silverlight applications needing to login to OAuth based services (Facebook, Twitter, Flicker…).

Bonus feature: Logout or “What goes up must come down“

After all the trouble with authentication, it would be nice if logging out was simple… and it mostly is. Presently the only way to properly log a user out of Facebook is by redirecting the user to logout.php with app id and session as parameters. One little problem is how do we get a hold of the session? Well, as it happens, session is part of the access token and can be extracted from it with little effort.

private string logout_format = 
    "http://www.facebook.com/logout.php?app_key={0}&session_key={1}&next={2}";

public void Logout(string access_token)
{
    access_token = HttpUtility.UrlDecode(access_token);
    int s = access_token.IndexOf("|");
    int e = access_token.LastIndexOf("|");
    string session = access_token.Substring(s + 1, e - s - 1);
    browser.Navigate(new Uri(string.Format(logout_format, app_id,
        session, HttpUtility.UrlEncode(OAuthUrl))));
}

If you are developing applications for Facebook, then you know that the old Facebook REST API has been replaced with the new Graph API. To make sure that my Facebook applications keep working, and considering the uncertain future of the Facebook Developer Toolkit, I decided to write my own Graph SDK - GraphLight.

In designing GraphLight, my major goals were to make it small and simple to use, and to be compatible with the asynchronous programming model supported by Silverlight. After some experimentation, I decided to use Reactive Extensions Library to make the most of the asynchronous nature of Silverlight.

GraphLight is very easy to use, as I will demonstrate with the following samples:

First, let’s initialize GraphLigh by providing it with a valid access_token and then get information about the current user:

    Profile Me;
    public MainPage_Loaded()
    {
        GraphApi.access_token = access_token;
        GraphApi.Me.Subscribe(OnMe);
    }
    private void OnMe(Profile profile)
    {
        me = profile;
        name.Text = me.name;
        about.Text = me.about;
        pic.Source = new BitmapImage(new Uri(me.Picture));
    }

Next, let’s get the list of friends:

    Me.Friends.Subscribe(
        freinds =>
        {
            foreach (Profile friend in friends)
                // do something application specific
        }
    );

Uploading a photograph is also quite easy:

    album.Upload(“Me wrestling with polar bear”, photoStream)
         .Subscribe(pid => status.Text = "Upload succesful pid=" + pid);

You can use reactive extensions to simplify complex asynchronous scenarios. For example, you can use ForkJoin to wait for all asynchronous downloads to finish, and then call the subscriber with the results:

    List<Photo> allPhotos = new List<Photo>();
    albums.Where(a => a.name != "Profile")
          .Select(b => b.Photos)
          .ForkJoin().Subscribe(
               v =>
               {
                   foreach (var photos in v)
                   {
                       allPhotos.AddRange(photos);
                   }
               }
          );

Fair warning:  GrahLight is not a fully supported, take-care-of-it-all library. If you like to tinker with your code and modify your library to meet your needs, then GraphLight could be for you. I would also recommend looking at similar libraries on CodePlex, for example Facebook Graph Toolkit.


If you’re building a Silverlight application for Facebook, you have two choices: (1) build a stand alone application and use Facebook Connect for authentication, or (2) create a canvas application that will appear on a Facebook site and use the parameters passed to iframe to establish a session. The former is well covered in the Facebook Toolkit documentation, but I couldn’t find any examples of how to embed a Silverlight application within a Facebook iframe. It took a few days worth of research and experiments to get it right and I hope this post will be helpful to anyone who is working on Silverlight canvas application for Facebook.

Embedding Silverlight into Facebook canvas

I know three ways of embedding Silverlight application into a Facebook canvas.Fbss

(1) Select the IFrame option for Render Method in Canvas section of the application settings and embed the Silverlight application inside the iframed page using standard methods (object tag, silverlight.js, etc.).  (2) Use <fb:iframe> tag in fbml based canvas. (3) Use fbml tag <fb:silverlight>. The <fb:silverlight> tag would be the preferred method, but according to the Facebook wiki, the tag is not implemented at this time. That leaves only options 1 and 2 available – embed Silverlight in iframe.  Whether you go with IFrame canvas or use <fb:iframe> tag in fbml, the following steps are the same:

More...


Comic Composer for Facebook

If you visited my projects page then you know about silverlight comic builder I am working on. Comic Composer for Facebook is the latest development bringing user created comics strips to Facebook platform. I am currently looking for beta testers to help me to prepare application for general release. Please, leave your comments and suggestions in this post.

  • Comic Composer for Facebook
  • Facebook Toolkit
  • Image tools