(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.