Expanding Facebook Scope from a Force.com Social Application

By default, the current Auth Providers implementation of social sign-on only requests the 'email' permission from Facebook. Learn how to request any set of permissions by leveraging the Facebook JavaScript SDK from a Visualforce page.

If you’ve watched me and Chuck presenting the Social Sign On with Authentication Providers webinar, you might remember us demonstrating social sign on into a customer portal running on Force.com, and mentioning that the Auth Provider requests only the email permission from Facebook. We plan to allow customization of the list of requested permissions in a future release, but, right now, the only data available via the Facebook access token is the authenticated user’s email address and basic information such as name, gender, locale and the user’s friends list.

Preparing for a workshop I’ll be presenting in July at the Cloud Identity Summit in Vail, CO, I got to thinking about whether I could expand the set of requested permissions (in OAuth 2.0 terms, the requested scope) to allow code in a customer portal to do more interesting things with the Facebook Graph API, such as retrieve the user’s photos and videos, publish to the user’s stream, and so on. It turns out that, with a bit of help from the Facebook JavaScript SDK, it is indeed possible to request additional permissions. I’ve uploaded the complete code demonstrating this as a Gist; here’s a line by line dissection of the relevant JavaScript code.

First, we load the Facebook library and give it the div it needs. For simplicity, I’m loading the library synchronously:

<script src="https://connect.facebook.net/en_US/all.js"></script&
<div id="fb-root"></div>

Now I can set up the list of required permissions, split them into an array, and initialize a string with the list of permissions we’ll be requesting from the user:

    // Get required permissions from the controller
    var permissions = '{!permissions}';
    var permlist = permissions.split(',');
    var reqperms = '';

I’m getting a comma-separated list of permissions from the controller, since it knows which permissions it needs, but you could set up the permissions list directly in the JavaScript if you wanted.

Now it’s time to initialize the Facebook SDK using the Auth Provider’s consumer key (aka application ID), also retrieved from the controller:

    FB.init({appId: '{!appId}', xfbml: true, cookie: true});

That done, we can get the user’s login status. Note that, since the user already logged in via the Auth Provider, we don’t need to call FB.login(), but we do need FB.getLoginStatus() so that the SDK picks up the fact that the user did log in:

    FB.getLoginStatus(function(response) {

In the callback passed to FB.getLoginStatus(), we test response.status and, if the user is logged in and has authorized the Auth Provider, we query the /me/permissions Graph API node to get the list of permissions already granted to the Auth Provider:

      if (response.status === 'connected') {
        // Check we have the permissions we want
        FB.api('/me/permissions', function (response) {

It’s straightforward now to iterate through the list of permissions and build the list of permissions to be requested:

          for (var i = 0; i < permlist.length; i++) {
              if (! response.data[0][permlist[i]]) {
                  if (reqperms !== '') {
                      reqperms += ',';
                  }
                  reqperms += permlist[i];
              }
          }

If we do need any permissions, we use FB.login() to request them from the  user:

          if (reqperms.length > 0) {
            // We need some permissions - ask for them
            FB.login(function(response) {
              if (!response) {
                alert('Error getting permission!');
              } else {
                location.reload(true);
              }
            }, {scope: reqperms});
          }

And that’s pretty much it. I discovered in writing this sample that it is possible for the user to de-authorize the Auth Provider in Facebook while they’re in the portal in another browser window. This results in an HTTP error when the controller tries to access the Graph API using the user’s (now invalid, since it’s in the context of the app) access token. Take a look at the controller code to see how to easily handle this by catching the FacebookException.

As I mentioned above, we intend to support custom scopes in a future release, but this simple tweak allows much richer social applications on Force.com in the meantime. Try it out and let me know how it works for you via a comment.

Published
June 29, 2012
Topics:

Leave your comments...

Expanding Facebook Scope from a Force.com Social Application