Introduction To Signed Requests

By the time you've gotten a couple introductory OpenSocial applications written, you may be wondering how you can take advantage of web services running on your external server to build a more sophisticated OpenSocial application.

In order for a web service to provide meaningful functionality, it will likely require the ID numbers of the users currently interacting with your OpenSocial application on the container. However, if your OpenSocial application sends any ID numbers directly, the values are vulnerable to manipulation by malicious users of your application.

Fortunately, the OpenSocial API provides a method to communicate OpenSocial ID numbers back to your server in a secure way, allowing for the construction of robust web service backed OpenSocial applications, using a portion of the OAuth authorization protocol.

This article will explain the method to make such secure requests from your OpenSocial applications, as well as the server-side process that you need to follow in order to verify that the data passed has not been tampered with.

About this article

This article is written assuming that you have an intermediate knowledge of the OpenSocial API, and some familiarity with requesting /wiki/spaces/a/pages/527111 using OpenSocial. It is also written under the assumption that you have access to an external server, and some experience writing server-side code for web applications.

What are signed requests?

OpenSocial applications may need to transmit certain pieces of data in a verifiable way to a third party site. For example, an application may want to share the OWNER's ID number with its database backend, stored on another server. While it is tempting to transmit this number in a normal GET or POST request, this approach has a security weakness. Because makeRequest calls are just JavaScript, it is possible for any user of an application to create makeRequest calls with whichever arguments they wish. Because the remote server cannot verify whether such requests originate from the application or the user, it has no way of differentiating the modified request from the legitimate one.

Let's assume that Alice Testington is using an OpenSocial application that communicates with an external web server. Typically, this application may be tempted to request Alice's OpenSocial ID number and transmit it to the remote site using the gadgets.io.makeRequest call.

In this example, the remote server looks for the opensocial_viewer_id parameter in the request and returns information about that user. If the application were a restaurant review app, this information might be a list of restaurants that Alice has reviewed. A banking app may return information about Alice's bank account.

Now imagine that Evil Testington were a malicious user of the application. Using Firebug or some other method of forging a request, they change the call to makeRequest and insert Alice's ID number instead of their own.

Even though this may not seem to be a big risk, it's happened in the past.

Signed requests were introduced to address this issue, and are based upon OAuth's parameter signing mechanism. Through the use of parameter signing, it is now possible for a gadget to request the container to send ID numbers along with a cryptographic hash that allows third party sites to verify that the numbers passed are indeed legitimate.

When a makeRequest is signed by the container, the container adds additional data to the request before forwarding it to the remote website. This data contains additional information such as the current OWNER and VIEWER of the app, the ID of the application making the request, and some additional information that your server can use to verify that the information added was not tampered with since the container sent the request.

Making a signed request in JavaScript

To make a signed request, you specify the gadgets.io.RequestParameters.AUTHORIZATION parameter, as shown here:

  function request(url) {
    var params = {};
    params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED;
    gadgets.io.makeRequest(url, response, params);
  };

The server will see the following querystring parameters added to the request:

  • opensocial_owner_id - The ID of the current owner, which matches the getId() value on the owner person object.
  • opensocial_app_url - The URL of the application making the request. Containers may alias multiple application URLs to a single canonical application URL in the case where an application changes URLs.

Additionally, the following parameters may optionally be added (depending on the container):

  • opensocial_viewer_id - The ID of the current viewer, which matches the getId() value on the viewer person object.
  • opensocial_instance_id - An opaque identifier used to distinguish between multiple instances of the same application in a single container. If a container does not allow multiple instances of the same application to coexist, this parameter may be omitted. The combination of opensocial_app_url and opensocial_instance_id uniquely identify an instance of an application in a container.
  • opensocial_app_id - An opaque identifier for the application, unique to a particular container. Containers that wish to maintain backwards compatibility with the opensocial-0.7 specification may include this parameter.
  • xoauth_public_key - An opaque identifier for the public key used to sign the request. This parameter may be omitted by containers that do not use public keys to sign requests, or if the container arranges other means of key distribution with the target of the request.

The server will also be passed the parameters oauth_consumer_key, oauth_nonce, oauth_signature, oauth_signature_method, oauth_timestamp, and oauth_token, which are used for validating the signed request. Use of these parameters will be explained later in this article.

Note that merely initiating a signed request is not enough to keep your requests from being impersonated - the third party server needs to validate that any information passed to it is valid. The following section will examine signed requests in more detail and give some server-side algorithms for validating these requests.

Validating signed requests on the remote server

The process to validate a signed request on your server will be different depending on your server configuration and which technologies you are using. Check the Validating Signed Requests page to see if a solution is available for the language of your choice.