views:

512

answers:

3

I'm building Pylons-based web application with RESTful API, which currently lacks any authentication. So I'm going to implement that and in order to avoid all the trouble and caution with storing user passwords, I'd like to use OpenID for authentication. What would be the best way to do this? Are these two things compatible? Are there existing REST APIs that use OpenID that I can take inspiration from?

+1  A: 

OAuth is a better fit for API usage. Here's an example of OAuth in use in Python: oauth-python-twitter. Leah Culver's python-oauth library is the canonical implementation of OAuth in Python, but python-oauth2 is a recent contender that is getting some buzz. As for inspiration, django-piston has support for using OAuth to do auth when creating RESTful APIs for Django, though the documentation isn't as nice as I'd like for that particular topic.

Hank Gay
The API is currently aimed at client-server scenario. Client is Flash app and server is Pylons webapp. There is currently no server-to-server stuff so don't need 3-legged stuff just yet. My current issue is how do I introduce "authenticated users" in the system without having to deal with storing passwords, sending password reminders, resetting passwords and so on. It's not immediately clear how OAuth helps me here, since in 2-legged version it just specifies how to sign requests.
Pēteris Caune
In that case, maybe one of the pastes at http://pylonshq.com/pasties/by_tag/openid will help.
Hank Gay
A: 

If you build API, you could check OAuth protocol. It's complementary to OpenID.

MBO
+2  A: 

I've now spent some time researching the options and would like to summarize the findings. First, a little bit more context -- I develop and control both the service and API consumer. Consumer is Flash-based app that is served from the same host the API is now and is supposed to be used in browser. No third party clients in sight yet.

So the question can be divided in two parts,

  • how do I do the OpenID authentication via API
  • how do I maintain the "authenticated" state in subsequent requests

For first part, OpenID authentication almost always includes interactive steps. During the authentication process there will most likely be a step where user is in OpenID provider's web page, signing in and pressing some "I agree" button. So API cannot and shouldn't handle this transparently (no "tell me your OpenID provider and password and I'll do the rest"). Best it can do is pass forth and back HTTP links that client has to open and follow instructions.

Maintaining "authenticated" state

REST APIs should be stateless, each request should include all the information needed to handle it, right? It wouldn't make any sense to authenticate against OpenID provider for each request, so some kind of session is neccessary. Some of the options for communicating session key (or "access token" or username/password) are:

  • HTTPS + BASIC authentication ("Authorization: Basic ..." header in each request)
  • Signing requests Amazon-style ("Authorization: AWS ... " header in each request)
  • OAuth: acquire Access Token, include that and a bunch of other parameters in each request
  • Cookie that stores session key ("Cookie: ... " header in each request)
  • Signed cookie that stores session information in the cookie itself

There's just one API consumer right now, so I chose to go for simplest thing that could possibly work -- cookies. They are super-easy to use in Pylons, with help of Beaker. They also "just work" in the Flash app -- since it runs inside browser, browser will include relevant cookies in the requests that Flash app makes -- the app doesn't need to be changed at all with respect to that. Here's one StackOverflow question that also advocates using cookies: RESTful authentication for web applications

Beaker also has nice feature of cookie-only sessions where all session data is contained in the cookie itself. I guess this is about as stateless as it gets. There is no session store on server. Cookies are signed and optionally encrypted to avoid tampering with them in client side. The drawback is that cookie gets a bit bigger, since it now needs to store more than just session key. By removing some stuff I didn't really need in the session (leftovers from OpenID authentication) I got the cookie size down to about 200 bytes.

Pēteris Caune