Accessing External Resources

In order to allow your OpenSocial Application to work with data located on remote servers, you can use a function called makeRequest. makeRequest allows you to get data from remote servers, and send data to remote servers.

Last.fm is an example of a site that uses web services to retrieve metadata, including artist photos. Here’s an example of fetching Cher’s photo from Last.fm:

function request() {
  var params = {};
  // Content types available at http://code.google.com/apis/opensocial/docs/0.7/reference/gadgets.io.ContentType.html
  params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
  var url = "http://lastfm-api-ext.appspot.com/2.0/?method=artist.getinfo&outtype=json&api_key=b25b959554ed76058ac220b7b2e0a026&artist=Cher";
  gadgets.io.makeRequest(url, response, params);
};

function response(obj) {
  /** obj.data contains an object corresponding with the JSON-encoded response **/
  output("Cher");
  output(obj.data.image_large);
};

request();

Validating Signed Requests

Ning Apps, are web applications - applications that send information of members of Ning Network to third-party servers and vice versa. Because these applications are from a third-party, how can we be guaranteed that someone won’t try to impersonate web request using a tool like, say, Firebug?

One solution is to use a signed request, based on OAuth’s parameter signing mechanisms. When someone does an action that triggers a web request, your Ning App can attach information about the social network container (Ning), the specific social network and the user themselves; this is combined with a cryptographic hash, so any impersonated requests with different information will return an error. You can also read a little bit more about signed requests on the OpenSocial wiki: http://wiki.opensocial.org/index.php?title=Introduction_To_Signed_Requests

Sounds Great. How Do We Implement This in our App?

We’ll show you some code that we use for one of our own Profile Apps, Status. The application is a basic status display application, which takes input from the user, appends some network information to it in the form of the Ning Network ID and timestamp, and saves and retrieves data to the backend. The data is stored on a third-party server which runs PHP, and has a file and directory structure similar to what’s shown:

/keys/ning.com.cert /lib/OAuth.php /helpers/SecurityHelper.php /actions/create.php gadget.js

Applications that run the OpenSocial 0.7 spec - such as Ning Apps, use Javascript to call social methods and send and receive requests. This is the makeRequest method, and in the Status Profile App, the makeRequest method is called as shown, in the file gadget.js:

var url = appUrl + '/gadget.php'
var params = {};
var postdata = {
    action : 'create',
    viewer_id : viewer.getId(),
            container: network,
    status_textarea : status_text
};

params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED;
params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
params[gadgets.io.RequestParameters.POST_DATA] = gadgets.io.encodeValues(postdata);

gadgets.io.makeRequest(url, statusSubmitted, params);

Without going into too much detail, while the makeRequest method calls gadget.php, the file takes the contents available in /actions/create.php:

if (SecurityHelper::isSignatureValid()) {
    $payload["query"] = array_merge($_GET, $_POST);
    if (SecurityHelper::requesterIsOwner()){
        $status_text = strip_tags($_POST['status_textarea']);
        try {
            // Saves the status here ...
            $payload["result"] = 'created';
        } catch ($e) {
            $payload["result"] =  $e->getMessage();
        }
    } else {
        $payload["result"] = 'not authorized';
    }
} else {
    $payload["validated"] = "This request was spoofed";
}

In /helpers/SecurityHelper.php:

require_once("lib/OAuth.php");

class SecurityHelper{
    /**
     * Check if the OAuth signature in the request is valid
     * code based on http://wiki.opensocial.org/index.php?title=Validating_Signed_Requests
    **/
    public static function isSignatureValid(){
        //Build a request object from the current request
        $request = OAuthRequest::from_request(null, null, array_merge($_GET, $_POST));

        //Initialize the new signature method
        $signature_method = new SignatureMethod();

        //Check the request signature
        @$signature_valid = $signature_method->check_signature($request, null, null, $_GET["oauth_signature"]);

        return ($signature_valid == true);
    }

    /**
     * Do we know if the request came from the gadget owner
     **/
    public static function requesterIsOwner(){
       return ( (!is_null($_REQUEST["opensocial_owner_id"])) && ($_REQUEST["opensocial_owner_id"] == $_REQUEST['opensocial_viewer_id']));
    }

}

class SignatureMethod extends OAuthSignatureMethod_RSA_SHA1 {
    protected function fetch_public_cert(&$request) {
        $filename = 'keys/' . $_REQUEST['xoauth_signature_publickey'];
        if (!file_exists($filename)) {
            throw new Exception('Certificate not found');
        }
        return file_get_contents($filename);
    }
}

The file /helpers/SecurityHelper.php includes our OAuth file and includes some additional methods, including fetch_public_cert, which returns the Ning Public Key that we make available at https://opensocialresources.appspot.com/certificates#container11. You can find the OAuth file at the URL http://oauth.googlecode.com/svn/code/php/OAuth.php - which is taken from an OAuth PHP library provided by Google. If you would like to look at more examples, you can view http://oauth.googlecode.com/svn/code/php/.

A xoauth_signature_publickey certificate should now be available to validate signed requests using the makeRequest method, along with oauth_consumer_key, opensocial_owner_id, opensocial_viewer_id and opensocial_app_id parameters. The certificate is available at http://developer.ning.com/certificates/ning.cert. Note that even though the ning.cert name is used, xoauth_signature_publickey will return “ning.com.cert”. Make sure to test the rename your certificate names appropriately when testing out your application.

In the case of the oauth_consumer_key, Ning differs from other social networking containers in that each Ning Network maps to a unique consumer key. For example, examplenetwork.ning.com will be returned rather than ning.com. Also note that domain-mapped Ning Networks also will point to its corresponding non-mapped domain. The way OpenSocial on Ning handles signed requests is based off of Orkut’s methods of validating signed requests at http://wiki.opensocial.org/index.php?title=Validating_Signed_Requests, with two major changes: