With version .8 of the OpenSocial standard, support was added for REST
APIs. The authentication mechanism chosen for those APIs was OAuth.
However, there are two flavors of OAuth, and this document attempts to
explain the different use cases that they support in OpenSocial, as
well as why the "2-legged" variant of OAuth is likely to be more
important for most OpenSocial containers to support first. For the details of the specification, see section "4. Request Authentication and Authorization Context" of http://www.opensocial.org/Technical-Resources/opensocial-spec-v08/restful-api-specification 2-legged or 3-legged The OAuth term is most frequently used when referring to 3-legged OAuth. This was a standardized version of a protocol that many vendors like Yahoo, Google, AOL, etc. had deployed which involved an end-user going through a "dance" where they start on the OAuth consumer site, and are redirected to the OAuth provider site where they are asked to approve access by the consumer site to their data. If their approval is given, they are then bounced back to the OAuth consumer site. While this "dance" has enabled a whole net set of applications and data-interoperability, the user experience can be confusing for an end-user (sort of like ballroom dancing with two partners at the same time). 2-legged OAuth is a term that is used to refer to another variant of OAuth which does not require this dance. This variant is also called Signed Fetch or Phone Home, especially in the OpenSocial community. In fact, the vast majority of actual REST API calls made on the Internet using OAuth are made using 2-legged OAuth, not 3-legged OAuth. The reason for that is that this is the feature that allows a gadget to make a connection back to the home server's of the developers who created the gadget. The following blog post contains an early description of this gadget feature: This Signed Fetch feature of OpenSocial allows a gadget to "phone home" to its home servers. The reason the OAuth dance is avoided is because those home servers do not have any pre-existing information about the end-user, so there is no need for the end-user to give approval to access that non-existing data. Use Cases for OpenSocial REST API There are two primary use cases for an OpenSocial container to expose a REST API
The following diagram may have orient the reader to the data flows, click the picture to see a larger version. Reverse Phone Home When a user adds a gadget to their profile, they are generally presented with some options to control what level of access that gadget has to their OpenSocial information such as friend list, activity stream, etc. Whatever UI flow is used to capture those permissions preferences can also be used to allow the user to decide what permissions the gadget's home servers should have to that data. A container could even choose to default to giving the gadget's home servers the same permission as the gadget. If the user later changes these permissions, or deletes the gadget using the UI flow that they use to manage gadgets today, those changes will similarly apply to the gadget's home servers. This combined UI enables the end-user to avoid having to go through a second UI flow in an OAuth dance to decide what permissions the gadget's home servers should have. More importantly, it offers a consistent way to edit or delete those permissions, because there is no existing standard UI flow for an end-user to manage those permissions outside the gadget framework. For example, what if a user deleted a gadget, but forgot to go to a different UI to delete that gadget's home server's access to the end-user's data? Now that we have avoided the OAuth dance, the gadget's home servers can make a REST API to the OpenSocial container to access the end-users data. However, that creates two security/identity challenges:
Note:
Previously we mentioned the Phone Home feature of OpenSocial. Those
calls also need to be digitally signed by the container who is sending
them, so that the gadget's home servers can verify their authenticity.
A container could choose to a shared secret to sign the phone home
requests, and then ask the developer to use the same shared secret to
sign the reverse phone home requests. The second problem is identifying the user. Fortunately, there is already a common user identifer that is shared by the container and the gadget's home servers. Whenever the gadget makes a phone home call to its home servers, the container adds the IDs of the gadget owner and viewer. The gadget's home servers can then store data locally about one of those user IDs. If it wants to make a REST API call for more data about the user, it can simply pass the same user ID. OpenSocial App Data Another advantage that 2-legged OAuth has in this scenario is that when a REST call is received by the OpenSocial container, it can easily map it to the gadget which is associated with the requesting server. If the server is asking for access to OpenSocial App Data, then the container needs to know which gadget's AppData to return, and this is made simpler by having the direct mapping between the home servers and gadget. In addition, if the home servers want to add information to the user's activity steram, or send a message to a user, then the container can attribute the source of that post/message to the gadget. Comparing URL Parameters: To help explain the reverse phone home feature, the following table compares the URL parameters used for phone home and reverse phone home:
Note that the oauth_signature can be done in both cases with the same shared secret (though some containers may prefer to sign phone home requests using a public/private key). The container will assign the oauth_consumer_key that should be used in reverse phone home calls, but a simple option for the container would be to use the same appid that they send on phone home calls. It is then the responsibility of the gadget's home servers to remember user IDs that it has seen in phone home calls, and when it wants to get more data about that user via a REST API call it should put that ID in the xoauth_requestor_id field that was specific in the .8 spec. Accepting both 3 legged & 2 legged While the section above describe how an OpenSocial container could accept 2-legged OAuth calls to its REST API, it can also accept 3-legged OAuth calls. The same API endpoint can be used for both types of calls, it just needs to detect whether an OAuth token is passed, in which case 3-legged OAuth is being used. In that case, the ID of the user's whose data is being requested would be extracted from the OAuth token, but the identity of the server's making the call would still be extracted from the oauth_consumer_key after validating the signature. |