Taking OAuth Beyond the 3rd Leg

(Or, Delegating Delegation)

There is nothing like a popular API to drive OAuth forward. As more developers transition to use Twitter’s new OAuth API, new requirements emerge. Existing sites based on Twitter use Twitter usernames and passwords for more than just calling the Twitter API. They use it as a sign-in solution for their own service, as well as to integrate with other Twitter-based applications.

There are many cases in which one third-party application uses functionality from another third-party application. For example, my iPhone Twitter client Twittelator, integrates with TwitPic to allow me to post photos directly from my phone. The way it works is that Twittelator has my Twitter username and password, and TwitPic uses the same credentials to offer its service.

When I gave Twittelator my Twitter credentials, I implicitly allowed it to act on my behalf without limitations. Everything my Twitter credentials can do, is technically fair game for this third-party application. Of course, applications should never abuse this power, but as long as they deliver expected results and don’t scare their users, people will be happy with the additional functionality.

Once Twittelator or TwitPic switches over to the OAuth API, this functionality breaks.

OAuth exchanges user credentials with token credentials that are issued to a specific 3rd party application. Most sites require developers to first register their application before being able to obtain authorization from the service’s users. What we need is the ability for Twittelator, using its token credentials, to get TwitPic to also act on behalf of the user.

This might be an interesting use case to standardize in the future, but we need a lot more implementation experience before we settle on a single pattern. Here are three ideas on how this can be implemented today. The key here is to make sure the user stays in control.

Keep in mind that these are just ideas and a very small subset of the possible approaches. These ideas simply imitate the current username-password “terms” and do not offer additional protections to the user. Once a token has been shared (using these methods) with another application, that other application can continue to act on behalf of the user until the token is revoked. To prevent shared tokens to be used by the other application without permission from the primary one, more complex solutions are needed which are beyond the scope of this post.

All or Nothing

The easiest way is for the server to keep a flag with each token issued, if that token is allowed to be used by a single client, or any client. The OAuth Core 1.0 specification only restricts the association of the temporary credentials (request token) to the client identity (consumer key). There is no such restriction on sharing the (access) token among multiple clients.

During the registration process, the developer is asked if the application should have the ability to share the token with other third-party applications. The developer choose one of three options:

  • Yes, access sharing is required for it operate. The user will be presented with the information with no ability to change the scope of the grant. If approved, the client will be able to share the token with other applications.
  • Yes, access sharing would enhance the experience but is not required. The user will have the option to grant or deny the addition scope and continue either way.
  • No sharing is needed. The user will not be asked about access sharing and continue using the normal single-application flow.

Once a set of token credentials is obtained, the application can share it with the other third-party application which will also access the user’s protected resources. This can be done using many ways, such as HTTP Basic Auth over HTTPS transmitting the token and secret as the username and password. The other application can then extract that information and use it to make OAuth-authorized requests.

Again, there is nothing to prevent the other application from using the token freely and the only way to stop it is to revoke the token completely. Service providers should consider the security threat of their applications to determine if such sharing model is appropriate for them.

Registered Sharing Scope

Similar to the previous method, the application developer registers the application and indicates that additional access sharing may be required. However, unlike the all-or-nothing approach, the developer is asked to select which other applications he would like to share access with, and which is optional or required.

When the user is asked to authorize access, he gets to see exactly which other applications will have access to his resources. If some are optional, the user is able to uncheck them if desired. This gives the user the final say with full understanding of who is going to have access. It is important to understand that this approval is a packaged deal and can only be revoked as a whole.

If the server allows for optional application sharing, it needs to provide the client with a way to find out which applications have been approved.

Dynamic Access Sharing Scope

A twist on the previous method, in which instead of asking for the access sharing at registration time, the OAuth protocol is extended to include an additional parameter that will list the client identifiers (consumer key) of the other applications to be shared with.

For example, given three applications with identifiers: ‘a1’, ‘b2’, and ‘c3’, an application can request user authorization by including a new parameter: example_oauth_share=”a1,!b2,c3″ (values are not percent-encoded for readability). This example reads: share access with a1 and c3 as optional applications and b2 as required. This of course is just a straw man proposal and is in no way a well thought extension.

The advantage of this approach is that the application developer can ask for additional access sharing without having to modify the application registration, and without requiring a special UI to select applications. It can also enable on-the-fly add-ons based on user actions. Keep in mind that any change to tokens already issued requires re-authorization from the user.

The Real Deal

These three ideas are not accomplishing much beyond what is currently practiced with usernames and passwords. All they do is enable the same pattern but with OAuth tokens instead. But at least they accomplish removing the need to share private credentials. Ideally, access sharing can only take place when the primary application is involved and has authorized it.

To make this happen, the application must not share its token credentials directly, but instead provide some other way for the other application to access protected resources. For example, serve as a proxy, signing requests for the other application by either acting as a middle tier or simply signing the requests and passing them back to the other application for execution.

The purpose of this post is not to solve this use case, but to get people thinking about the problem and come up with new ways to address it. So what’s your idea?

Update: More thoughts on access sharing.

11 thoughts on “Taking OAuth Beyond the 3rd Leg

  1. Isn’t part of the problem that OpenID/OAuth don’t have a non-browser workflow, which requires clients on resource constrained devices to launch a browser just to collect a token? I’d prefer it if my credentials were stored in an OS-level keychain vault, and if phone applications could ask some OS service to go grab an access token on my behalf. Then, it would be nice, if OpenID/oAuth had a mechanism for non-browser authentication/authorization.
    Sharing scope between clients seems like a way to enable proxy devices to grab tokens for less capable devices, but I think having a protocol that doesn’t rely so heavily on HTML mechanisms would be better for mobile devices. Even given how nice mobile Safari is on iPhone or Android, it still consumes massive phone resources to launch a browser, it chews up battery life, and has poor UX latency.

  2. (This Google OpenID doesn’t look very… hmm… usable)
    This has nothing to do with OpenID.
    It doesn’t matter how a desktop application stores your credentials. If it has to share them in plain text with another entity, you are leaking passwords.
    Yes, OAuth could benefit from alternative flows that do not require browser redirection (see http://www.hueniverse.com/hueniverse/2009/02/beyond-the-oauth-web-redirection-flow.html), but that has nothing to do with how an authorize application can further delegate the access to granted it.
    In other words, your comments have nothing to do with this post…

  3. In the case of Twittelator/TwitPic, couldn’t Twittelator pass (as a parameter) to TwitPic a pre-signed Twitter API URL? This would allow TwitPic to make a call on behalf of the user, utilizing authorization credentials given to Twittelator without leaking long-lived authorization credentials to TwitPic. Seems like a relatively easy way to work around this particular problem.

  4. First, Twittelator will need to know what API calls TwitPic needs to make. It will also need the parameters or payload for the calls. So in practice, TwitPic will need to use Twittelator as a proxy.

  5. TwitPic can specify the necessary API URLs as part of their documentation for calling their API.
    As for the parameters/payload, that’s only true if they’re passed as part of the query string or as an application/x-www-form-urlencoded POST body. Unfortunately, that’s what Twitter uses for updating status, so you’re right, it won’t work. Not unless Twitter changes to accepting XML/JSON PUT/POST bodies instead, since those bodies aren’t part of the signature.

  6. Eran,
    We are developing an API and have been instructed to use OAUTH. However, after a user has granted access, our client wants the access to persist indefinately until revoked by the user. Does OAUTH support this?

    • Could the tokens be shared between the third party sites?In that case can OAuth be adapted to include delegation between the sites?Also can a third party site delegate the accesses granted to it to another site ?How can this be done with the current OAuth system?

      • The problem with 1.0 is that to use a token, the client needs both the token secret and the client secret, and handing the client secret out to third parties is not a good idea. This is solved in 2.0, but due to current lack of signatures, is a bit more challenging.

      • Can there be a restriction on the number of calls which can be made by Twittelator to delegate tokens to a third party application like Twitpic?

Comments are closed.