Pownce’s API chief Shawn Allen recently opened a Google group to discuss the upcoming Pownce public API trying to capture the same community buy-in the Twitter group is known for. Shawn raised the question of API security and authentication, something I have been thinking about for a couple of months now (building a somewhat similar service). The goal is to try and find the right balance between ease of use for developers, security and privacy. Nouncer requires a solution that will address multiple client needs (desktop application, AJAX script, server-side web script), and will be easy to use in multiple technologies. This message was originally posted to the Pownce API group and has been revised for the Hueniverse blog.
There are three separate (but related issues when considering API security:
Authorization is the process of validating user credentials to allow access to API resources. This can be done very simple with Basic HTTP authentication (can be done in HTTPS which is secure) or with an authorization provider solution (OpenID, OAUTH, Google AuthSub, Windows Live Id – aka Passport, Facebook Login, etc). The good thing about Basic HTTP authentication is that it’s very easy to use, and when combined with HTTPS is also secure. However, it requires authentication on every API call, and most importantly, it requires the client application to keep a copy of user credentials. This is a known problem with Twitter apps where the non-Twitter sites ask and store user passwords to offer their services. OpenID on the other hand (and other similar protocols) requires redirection of the client which is not (directly) compatible with AJAX and other scripting solutions. It also requires maintaining state information about the authentication transaction which is a hassle for most clients.
The need to prevent 3rd parties from gaining access to user passwords is very strong. Especially since users tend to use the same password over many sites. The author of the next big Pownce or Twitter app might very well be someone using the app to get access to your password. I have been playing around with using OpenID in an API wrapper which looks very promising. The nice part is that it doesn’t require any encryption work from the client.
Another ongoing effort is OAUTH, an authentication protocol meant to provide a framework for users to grant services access to their private network resources (such as their Twitter account, Flickr photos, etc.). OAUTH started as an effort to integrate OpenID into Twitter and Ma.gnolia Dashboard Widgets, and evolved into an upcoming specification for secure open authentication. It looks promising and has some bright individuals behind it, but it’s too early to say if it will fit within the Nouncer platform.
Once authenticated, most APIs allow using a session token (with or without expiration) to be used in place of constant authentication. Combined with an OpenID-like system, a user signs in and the client application gets a token to use for user-like access (same or subset of the user rights on the resource). Sessions also allow state-based API calls where an activity can be performed by a set of API calls with continuity (usually combined with a cookie). The biggest concern about sessions is hijacking where someone gets hold of the session token and can make calls pretending to be the user. Using HTTPS throughout the protocol will solve this problem but is usually an overkill. Typical implementation would include some sort of public key signature on the content of the API request together with a nonce (special token which can only be used once).
Most sites use a session token that is unique and random. Tokens are impossible to guess and are also tied on the server side to a specific user, IP address, and expiration. Users sign-in, get the token cookie, and each consecutive call only needs to lookup the cookie in the database, validate the source IP address, make sure it is still valid (did not expire) and allow access to the owner of the cookie. A single attempt to use a token from the wrong IP address (should) invalidates the token. This technique is vulnerable to IP spoofing but is usually good enough for most applications and is very simple to implement. The client has no extra work expect for grabbing the cookie value and using it as a parameter in API requests.
The more complex form of session management involves signatures. The user/client authenticate with the server and gets a session token as well as an secret. The secret is received on a secure channel or is encrypted with a public key. The client construct the API call (usually a REST URL) and then calculate a signature using the secret and the API call parameters. The signature is sent together with the API call. When the server gets the request, it takes the signature and then checks if the API and secret (which is not transmitted) match the signature (by signing it again and comparing results). This proves the request came from the authorized session owner. To prevent replay attacks (someone grabs the API request and use it unchanged to make API requests), the client adds a nonce to the API request before signing it. The server will only honor each nonce one time from the client, so if captured by someone else, the server will refuse the call. Some implementations void the entire session/secret when such a failed attempt occurs.
If the API call itself is confidential (the fact that a user posted a message, or the content of the message, etc), the entire API interface must be encoded. In this case HTTPS would be the simplest solution available without any additional work. In the context of micro-blogging and casual internet messaging, this is rarely needed. It would be nice if any API call that can be made over HTTP will also be available over HTTPS. From an implementation standpoint (service side) this is very simple to provide (but it does come at a CPU cost).