The OAuth Proxy
is designed to make it easier for gadgets to access a user's private data on another website. However, things get much more complicated if a gadget is running on a social network where the person viewing the gadget is not the same as the data-owner who added the gadget, and who gave the gadget access to their data on another website. This is best explained by example.
Lets say that the fictional ecoffee.com website allows its users to order different types of coffee beans online, and keeps track of their favorites. They might create an OpenSocial gadget to allow one of their customers to share their list of favorite coffee beans with their friend list on a social network site. Tom has an account with ecoffee.com and logs in as username "tommyboy." He also has an account on an OpenSocial network such as orkut.com, but logs in as "tommy215." When he adds the ecoffe.com gadget, the following happens:
- The gadget tries to request his coffee bean list from ecoffee.com, but it fails because Tom has not gone through the OAuth Authorization flow.
- So the gadget then prompts Tom to go through flow, and once Tom confirms this is okay on the ecoffe.com website, that site returns an OAuth token which orkut.com saves to be used in the future whenever Tom runs that gadget.
- When the gadget next makes a request for Tom's coffee bean list, that OAuth token will be sent by orkut.com, but in addition orkut.com will send along Tom's OpenSocial ID which is a unique ID that orkut.com assigned to his tommy215 user account. That enables the ecoffee.com website to store the fact that this orkut.com OpenSocial ID maps to the local tommyboy user account on ecoffee.com.
That account pairing process only needs to be done once. In the future when Tom uses that gadget, both the OAuth token and his orkut.com OpenSocial ID will be sent along. The ecoffee.com website can use either of those to lookup the local user account with which they are associated. Now lets imagine that later, Sara views Tom's orkut.com social network page, and it includes the ecoffee.com gadget. In that case, the following happens:
- The gadget tries to request the coffee bean list from ecoffee.com for Tom. However because Tom is not the one viewing the page, orkut.com does not send the OAuth token, instead it sends Tom's OpenSocial ID as the page owner, and Sara's OpenSocial ID as the page viewer
- The ecoffee.com servers receive the request, and use Tom's OpenSocial owner ID to lookup the local user account with which it was previously paired
- In addition, the ecoffee.com servers detect that Tom is not the viewer of the page, so it uses the OpenSocial API of orkut.com to detect whether Sara is a friend of Tom's
- Assuming Sara is a friend of Tom's, the ecoffee.com servers would return Tom's coffee bean list. However if Sara were not a friend of Tom, then it might simply return the most popular beans on the ecoffee.com website as opposed to Tom's personal favorites
An additional possibility is that Sara might also be an ecoffee.com user who has installed the coffee.com gadget. In that case, if they are friends on this social network, then in step 4 instead of just returning Tom's coffee bean list, it could return both Tom & Sara's list of favorite coffee beans so that the gadget could display their shared interests.
For a website like ecoffee.com to support this type of scenario, that website needs to be OpenSocial aware. That server is normally referred to as the "OAuth SP (service provider)" in OAuth terminology or the "gadget home server" in OpenSocial terminology. For the rest of this document, we will refer to it as the OpenSocial SP. When an OpenSocial SP receives a data request, it needs to look for not only for an OAuth token, but it also need to look for the additional URL parameters in each data request from the remote OpenSocial container that identify the viewer of the gadget (Open Social Viewer), and owner of the page where the gadget is installed (Open Social Owner). The OpenSocial SP then needs to map those remote OpenSocial user identifiers to its local user account database.
In step 1 above when Sara is accessing Tom's page, the example states "because Tom is not the one viewing the page, orkut.com does not send the OAuth token." That is done for security reasons. If orkut.com did send the OAuth token, then a traditional OAuth SP that is not OpenSocial aware would assume the request was being made on Tom's behalf, and it would allow Sara full access to Tom's account, even if they were not friends. If Tom had given permission for the ecoffee.com gadget to edit his ecoffee.com account, such as to order more beans, then Sara could even use the gadget to place such an order. In fact, if Sara was even more malicious, she could modify the gadget code itself since technically that runs within her web browser, and therefore she could use the modified code to gain complete read and edit access to Tom's ecofee.com account. Since the OpenSocial container does not send the OAuth token in this scenario, we avoid this problem, however it does require websites that want to become an OpenSocial SP to do some extra work.
For the OpenSocial SP developer, the first step is to support gadget access via the OAuth Proxy in the simple mode (where viewer=owner). The major additional work is to implement step 3 in the example above where Tom is using the gadget. That is the step where the account pairing is done. The SP has three technical options for when to do this pairing, and any of them will work, so it is up to the SP to decide which to use.
- When the user goes through the OAuth approval flow on the SP's website
- When the OpenSocial container's OAuth Proxy swaps the OAuth request token for the OAuth access token
- The first time the SP receives a data request with the OAuth access token
For technical details on how to extract the OpenSocial ID information from the URL, please refer to the makeRequest()
No matter which of these three options are used, the SP will now need to store a table that accepts the OpenSocial ID sent by the OpenSocial Container and maps it to a local user account. If the OpenSocial SP developers wants to support multiple OpenSocial containers, then it is important ro remember that different OpenSocial Container's might use the same OpenSocial ID for completely different users, so in that case it is important to use the combination of the OpenSocial ID and OpenSocial Container to perform the mapping to a local user account.
The next step for the OpenSocial SP development is to implement steps 2-4 in the example above where Sara is using the gadget. There are four parts to this aspect that the OpenSocial SP must support:
- Accept (and validate) a call from the gadget which uses the makeRequest() feature with signed authorization and extract the OpenSocial owner and viewer ID
- Map the OpenSocial Owner ID from the signed fetch call to a local user account
- Perform any SP specific business logic to decide whether to allow the requested operation, including possibly checking whether the viewer is a friend of the owner using the standard OpenSocial API
- Perform the requested operation and return the results
Once the OpenSocial SP has finished this work, the gadget can be finished. Fortunately for the gadget developer, there is very little additional work to interface with the OAuth Proxy in the social mode (where viewer != owner) once the gadget already supports the simple mode (where viewer=owner). In social mode the gadget should always use the same makeRequest()
feature with signed authorization (and it does not matter what value it sets for the OAUTH_USE_TOKEN
flag because the OpenSocial container will always automatically block sending the OAuth token.) However, in that social mode the gadget will probably show a different user interface to the viewer, and may offer different features. It is up to the gadget developer to decide how to make their gadget interesting in this type of social situation