So, I've finally gotten a chance to take a look at Blaine Cook's oauth scheme. Basically, here's how it works:
- the service provider (in this case, Pownce) issues an API key and shared secret to a consumer (the author of a client) - the client requests a one-time token from the service provider that can then be exchanged for an "auth token" - the client signs subsequent requests using a hash of: the shared secret, the auth token, the API key, the request URI, a nonce, and a timestamp - the client chooses which hashing algorithm to use, and includes the name of the algorithm in the request signature
- it requires consumers to pre-register with the service provider - it requires signed requests
The ugly thing about the (obviously very old, probably stale) spec that I read is that, unlike AuthSub, oauth dictates that requests be signed via query string parameters. If we were to implement something like this, I would most certainly do all of the auth-specific stuff in the HTTP Authorization header.
Any thoughts? What are some of your favorite APIs, and what do you like or not like about their authentication schemes?
Cheers, -- Shawn Allen sh...@stamen.com +1 415 558 1610
So, Mike and I had a little talk about oauth today. I agree with him that the whole API key/shared secret deal is probably overkill for Pownce, and I worry that the AuthSub-style third party auth solution of bouncing users to the browser just won't cut it for us.
What I like about oauth is the way they use the request URI to sign to the request itself. Because it dictates that auth parameters go in the query string, they have a nice way of canonicalizing the other parameters and including those as hash parameters. Amazon and AuthSub do something similar: they hash the HTTP method and request URI, including query string parameters.
The last thing I want to do is make up our own authentication scheme, but none of the ones I've mentioned is a perfect fit for Pownce. Does anyone see a problem with picking one that works reasonably well and either discarding the parts of it that don't work or extending it with new ones? For instance, it might make sense for us to just beef up the initial token exchange with SSL, stick with WSSE for request signing, and possibly add an additional parameter to the Authorization header that encodes the request URI like AWS, AuthSub and oauth do.
As long as the request URI information isn't hashed into the PasswordDigest, this still conforms to WSSE. RequestDigest could be a hash of the shared secret, the HTTP method, and the request URI. Pownce would require this parameter and reject requests for which it's invalid.
Another thing Mike's reminded me to consider (and this apparently the reason that oauth puts the credentials in the query string) is that there are a lot of cases in which clients may not be able to modify request headers (Flash, specifically, is currently thwarting my attempts to do so--WTF?). Proxies also mess with headers in some environments, and sometimes even munge the request methods (hello? PUT, OPTIONS and HEAD are methods, too!). I've already planned ahead for this eventuality and written some middleware that accounts for the X-HTTP-Method-Override header.
Aaaanyway... there's still a lot to consider as far as authentication goes. For now I think I'm going to punt on it and focus on getting the request/response formats hammered out so that you all can see how this thing's going to work.
> So, I've finally gotten a chance to take a look at Blaine Cook's > oauth scheme. Basically, here's how it works:
> - the service provider (in this case, Pownce) issues an API key and > shared secret to a consumer (the author of a client) > - the client requests a one-time token from the service provider that > can then be exchanged for an "auth token" > - the client signs subsequent requests using a hash of: the shared > secret, the auth token, the API key, the request URI, a nonce, and a > timestamp > - the client chooses which hashing algorithm to use, and includes the > name of the algorithm in the request signature
> - it requires consumers to pre-register with the service provider > - it requires signed requests
> The ugly thing about the (obviously very old, probably stale) spec > that I read is that, unlike AuthSub, oauth dictates that requests be > signed via query string parameters. If we were to implement something > like this, I would most certainly do all of the auth-specific stuff > in the HTTP Authorization header.
> Any thoughts? What are some of your favorite APIs, and what do you > like or not like about their authentication schemes?
Personally, I really like Twitter's approach of just using standard Basic Auth. That would make it impossible to track or limit what client programs are allowed access, though.
On Jul 26, 6:55 am, Shawn Allen <sh...@stamen.com> wrote:
> Hey everyone,
<snip>
> - it requires consumers to pre-register with the service provider > - it requires signed requests
> The ugly thing about the (obviously very old, probably stale) spec > that I read is that, unlike AuthSub, oauth dictates that requests be > signed via query string parameters. If we were to implement something > like this, I would most certainly do all of the auth-specific stuff > in the HTTP Authorization header.
> Any thoughts? What are some of your favorite APIs, and what do you > like or not like about their authentication schemes?
To me, the most ugly thing about this is the crypto impact on old/ clapped-out devices. Doing RSA Crypto (or even MD5 signing) is not a nice thing to ask a Java enabled phone to do for each post, query or update.
Apart from that, the oauth system looks strongly secure. Almost certainly more secure than is nescessary for this application.
why dont we just use Google's AuthSub? i thought oauth is new?
anyway, this is what i am thinking of doing for my site. the only problem you really have with the original protocol i think is that your first authentication for the auth token is over plaintext. why dont you just do that part over SSL? the other missing piece is that you dont take data integrity into account. on subsequent calls that use the token, just include a hash of the payload. so something like this...
server client <--------SSL(getAuth(username, password) SSL(SHA-1(username, password, timestamp)------>
i think having a sequence number would be even better, but not really necessary for your sake. this scheme is almost like the message digest according the HTTP spec. it was meant to be a replacement for basic auth in HTTP. you can add stuff like, the client chooses the hash alg and stuff, but like, people usually say SHA-1 or MD5 anyway and MD5 is vuln.
as for the unreliable timestamp of the nonce, it all depends on how you package the payload. essentially, you can time it out whenever you want. you are afraid of large files where the time to transfer is greater than your timeout time right? i dont think you have to worry about that. you can either split up your file, in which case, when a token times out, you can just get another one and send the subsequent chunks with the new token. secondly, you can just do it as a whole tcp stream. then it only matters when you start sending it. to implement this is a little more tricky because it requires you to peek into the buffer. if i were you i'd just chunk a file and send them separately. granted there will be more overhead, but i think its negligible compared to all the atom/xml stuff you're using anyway.
<#
On Jul 25, 3:55 pm, Shawn Allen <sh...@stamen.com> wrote:
> So, I've finally gotten a chance to take a look at Blaine Cook's > oauth scheme. Basically, here's how it works:
> - the service provider (in this case, Pownce) issues an API key and > shared secret to a consumer (the author of a client) > - the client requests a one-time token from the service provider that > can then be exchanged for an "auth token" > - the client signs subsequent requests using a hash of: the shared > secret, the auth token, the API key, the request URI, a nonce, and a > timestamp > - the client chooses which hashing algorithm to use, and includes the > name of the algorithm in the request signature
> - it requires consumers to pre-register with the service provider > - it requires signed requests
> The ugly thing about the (obviously very old, probably stale) spec > that I read is that, unlike AuthSub, oauth dictates that requests be > signed via query string parameters. If we were to implement something > like this, I would most certainly do all of the auth-specific stuff > in the HTTP Authorization header.
> Any thoughts? What are some of your favorite APIs, and what do you > like or not like about their authentication schemes?
> Personally, I really like Twitter's approach of just using standard > Basic Auth. That would make it impossible to track or limit what > client programs are allowed access, though.
> To me, the most ugly thing about this is the crypto impact on old/ > clapped-out devices. Doing RSA Crypto (or even MD5 signing) is not a > nice thing to ask a Java enabled phone to do for each post, query or > update.
i dont understand what you mean by "ugly"? which scheme that was mentioned does RSA? is there a link to benchmarks for j2me on phones running MD5? currently, my company is implementing xmlrpc calls to a server from j2me and .net compact smartphones. they seem to be doing SHA-1 pretty ok.
it would be ashame to cripple the security of the protocol because of supposed limitations on a certain type of hardware. on the other hand, it may be worthwhile to design a "no security" option. this all depends on how well pownce wants to protect themselves.
> Apart from that, the oauth system looks strongly secure. Almost > certainly more secure than is nescessary for this application.
when doing "security stuff", you really have to do a threat assessment. basically, you have to say, "what i am protecting myself against?" depending on the answer, the protocol will be different. i'm not sure saying "more secure than is necessary" makes any sense at this point in time. from shawn's previous protocol and discussions with him, it sounds like he wants to implement, authentication and data integrity.
> The last thing I want to do is make up our own authentication scheme, > but none of the ones I've mentioned is a perfect fit for Pownce. Does > anyone see a problem with picking one that works reasonably well and > either discarding the parts of it that don't work or extending it > with new ones? For instance, it might make sense for us to just beef > up the initial token exchange with SSL, stick with WSSE for request > signing, and possibly add an additional parameter to the > Authorization header that encodes the request URI like AWS, AuthSub > and oauth do.
i think you're heading in the right direction. having the URI in the hash just narrows the range of things people can do by replaying the message. i think any replay attacks can be mitigated by including the URI, payload digest, and nonce in the "auth key", including the other normal stuff like the username and token of course.
why do they have to change the header? why dont you do something like xmlrpc or REST?
1. Looking at http://www.xml.com/pub/a/2003/12/17/dive.html that is proposed to be used, possibly: I was thinking perhaps Pownce could provide the nonce and timestamp. With each response Pownce also gives a new nonce and timestamp to be used in any next request. Pownce remembers this new nonce + timestamp in their back end for this particular (3rd party client-app, usertoken) combination. Clients should always use the latest nonce + timestamp provided to them. That way you don't have to deal with timing issues, replay is virtually impossible because you would need to know the hashed password in order to create the next base64(sha1(nonce+timestamp+md5(pwd))). Rename nonce +timestamp to newnonce (ie something that is time independent).
2. Any security issues are transfered to the place of the 3rd party apps: they may store the gathered hashed passwords in their databases which might be compromised at some point, etc. etc. For this (and other) reason(s) I think Pownce should limit what is possible with their APIs.
The thing I like more about Twitter's auth is that since they use Basic Auth, it is really easy for them to rate limit based on authenticated userid instead of API key. I think that's a much better way to control access for client apps that may get surges in adoption.
BTW, the service could easily require a specific hash to appear in the passed user-agent for it to accept requests from clients. This would allow them to shut down specific clients temporarily or permanently while devs fix issues and get a new hash to distribute with a fixed version of their app.
-Mykoleary
On Jul 25, 7:52 pm, "Ed Finkler" <funkat...@gmail.com> wrote:
> Personally, I really like Twitter's approach of just using standard > Basic Auth. That would make it impossible to track or limit what > client programs are allowed access, though.
I like the idea of using a session-key style idea (ala AuthSub, Facebook, YouOS), but I really hate API keys. It's just annoying to have to register every little piece of code with the service.
BasicAuth is nice for username/password, but what if another auth scheme (OpenID) is introduced to Pownce -- what then? A session-key- based system does not care how you authenticate.
Of course, the most basic auth system of this type just redirects to the service, giving it the return_to url:
Now example.com can use session_key to communicate with the Pownce API.
SSL can be used to prevent session_key from being stolen.
To prevent a false session_key (borrowing a page from OpenID), force example.com to communicate directly with pownce.com first and get a secret key (passing in the return_to URL for the secret to be used with) for this session only. Do the redirect like so:
> So, I've finally gotten a chance to take a look at Blaine Cook's > oauth scheme. Basically, here's how it works:
> - the service provider (in this case, Pownce) issues an API key and > shared secret to a consumer (the author of a client) > - the client requests a one-time token from the service provider that > can then be exchanged for an "auth token" > - the client signs subsequent requests using a hash of: the shared > secret, the auth token, the API key, the request URI, a nonce, and a > timestamp > - the client chooses which hashing algorithm to use, and includes the > name of the algorithm in the request signature
> - it requires consumers to pre-register with the service provider > - it requires signed requests
> The ugly thing about the (obviously very old, probably stale) spec > that I read is that, unlike AuthSub, oauth dictates that requests be > signed via query string parameters. If we were to implement something > like this, I would most certainly do all of the auth-specific stuff > in the HTTP Authorization header.
> Any thoughts? What are some of your favorite APIs, and what do you > like or not like about their authentication schemes?
Anything that requires header access is a pain for simple apps... BasicAuth can be done in the URL (user:pass@), but other than that, requiring special content in the Authorization header or similar just makes things more complicated....
On Jul 25, 10:48 pm, Shawn Allen <sh...@stamen.com> wrote:
> So, Mike and I had a little talk about oauth today. I agree with him > that the whole API key/shared secret deal is probably overkill for > Pownce, and I worry that the AuthSub-style third party auth solution > of bouncing users to the browser just won't cut it for us.
> What I like about oauth is the way they use the request URI to sign > to the request itself. Because it dictates that auth parameters go in > the query string, they have a nice way of canonicalizing the other > parameters and including those as hash parameters. Amazon and AuthSub > do something similar: they hash the HTTP method and request URI, > including query string parameters.
> The last thing I want to do is make up our own authentication scheme, > but none of the ones I've mentioned is a perfect fit for Pownce. Does > anyone see a problem with picking one that works reasonably well and > either discarding the parts of it that don't work or extending it > with new ones? For instance, it might make sense for us to just beef > up the initial token exchange with SSL, stick with WSSE for request > signing, and possibly add an additional parameter to the > Authorization header that encodes the request URI like AWS, AuthSub > and oauth do.
> As long as the request URI information isn't hashed into the > PasswordDigest, this still conforms to WSSE. RequestDigest could be a > hash of the shared secret, the HTTP method, and the request URI. > Pownce would require this parameter and reject requests for which > it's invalid.
> Another thing Mike's reminded me to consider (and this apparently the > reason that oauth puts the credentials in the query string) is that > there are a lot of cases in which clients may not be able to modify > request headers (Flash, specifically, is currently thwarting my > attempts to do so--WTF?). Proxies also mess with headers in some > environments, and sometimes even munge the request methods (hello? > PUT, OPTIONS and HEAD are methods, too!). I've already planned ahead > for this eventuality and written some middleware that accounts for > the X-HTTP-Method-Override header.
> Aaaanyway... there's still a lot to consider as far as authentication > goes. For now I think I'm going to punt on it and focus on getting > the request/response formats hammered out so that you all can see how > this thing's going to work.
> Cheers, > Shawn
> On Jul 25, 2007, at 3:55 PM, Shawn Allen wrote:
> > Hey everyone,
> > So, I've finally gotten a chance to take a look at Blaine Cook's > > oauth scheme. Basically, here's how it works:
> > - the service provider (in this case, Pownce) issues an API key and > > shared secret to a consumer (the author of a client) > > - the client requests a one-time token from the service provider that > > can then be exchanged for an "auth token" > > - the client signs subsequent requests using a hash of: the shared > > secret, the auth token, the API key, the request URI, a nonce, and a > > timestamp > > - the client chooses which hashing algorithm to use, and includes the > > name of the algorithm in the request signature
> > - it requires consumers to pre-register with the service provider > > - it requires signed requests
> > The ugly thing about the (obviously very old, probably stale) spec > > that I read is that, unlike AuthSub, oauth dictates that requests be > > signed via query string parameters. If we were to implement something > > like this, I would most certainly do all of the auth-specific stuff > > in the HTTP Authorization header.
> > Any thoughts? What are some of your favorite APIs, and what do you > > like or not like about their authentication schemes?
> I like the idea of using a session-key style idea (ala AuthSub, > Facebook, YouOS), but I really hate API keys. It's just annoying to > have to register every little piece of code with the service.
> BasicAuth is nice for username/password, but what if another auth > scheme (OpenID) is introduced to Pownce -- what then? A session-key- > based system does not care how you authenticate.
> Of course, the most basic auth system of this type just redirects to > the service, giving it the return_to url:
> Now example.com can use session_key to communicate with the Pownce > API.
> SSL can be used to prevent session_key from being stolen.
> To prevent a false session_key (borrowing a page from OpenID), force > example.com to communicate directly with pownce.com first and get a > secret key (passing in the return_to URL for the secret to be used > with) for this session only. Do the redirect like so:
> Now the client can see if this secret matches the one from earlier > then session_key is valid!
> On Jul 25, 6:55 pm, Shawn Allen <sh...@stamen.com> wrote:
> > Hey everyone,
> > So, I've finally gotten a chance to take a look at Blaine Cook's > > oauth scheme. Basically, here's how it works:
> > - the service provider (in this case, Pownce) issues an API key and > > shared secret to a consumer (the author of a client) > > - the client requests a one-time token from the service provider that > > can then be exchanged for an "auth token" > > - the client signs subsequent requests using a hash of: the shared > > secret, the auth token, the API key, the request URI, a nonce, and a > > timestamp > > - the client chooses which hashing algorithm to use, and includes the > > name of the algorithm in the request signature
> > - it requires consumers to pre-register with the service provider > > - it requires signed requests
> > The ugly thing about the (obviously very old, probably stale) spec > > that I read is that, unlike AuthSub, oauth dictates that requests be > > signed via query string parameters. If we were to implement something > > like this, I would most certainly do all of the auth-specific stuff > > in the HTTP Authorization header.
> > Any thoughts? What are some of your favorite APIs, and what do you > > like or not like about their authentication schemes?
On Jul 26, 1:47 am, Jimmy <jimmy.s...@gmail.com> wrote:
> Hi,
> 1. > Looking athttp://www.xml.com/pub/a/2003/12/17/dive.htmlthat is > proposed to be used, possibly: I was thinking perhaps Pownce could > provide the nonce and timestamp. With each response Pownce also gives > a new nonce and timestamp to be used in any next request. Pownce > remembers this new nonce + timestamp in their back end for this > particular (3rd party client-app, usertoken) combination. Clients > should always use the latest nonce + timestamp provided to them. That > way you don't have to deal with timing issues, replay is virtually > impossible because you would need to know the hashed password in order > to create the next base64(sha1(nonce+timestamp+md5(pwd))). Rename nonce > +timestamp to newnonce (ie something that is time independent).
you're sort of describing a sequence number. a real sequence number works better in this case. there are some problems with your proposal. they are all corner cases where messages arrive late and/or out of order. if you use a monotonically increasing sequence number, then those cases can be dealt with.
> 2. > Any security issues are transfered to the place of the 3rd party apps: > they may store the gathered hashed passwords in their databases which > might be compromised at some point, etc. etc. For this (and other) > reason(s) I think Pownce should limit what is possible with their > APIs.
what do you mean "any security issues"? i think i'm missing the point of this statement. especially the "should limit what is possible with their APIs" part. pownce needs to provide layer 5-6 security. application specific stuff sure, but the protocol should be secure and made so by pownce.
On Jul 25, 10:48 pm, Shawn Allen <sh...@stamen.com> wrote: ...snip...
> Aaaanyway... there's still a lot to consider as far as authentication > goes. For now I think I'm going to punt on it and focus on getting > the request/response formats hammered out so that you all can see how > this thing's going to work.
Sounds like a realistic path thru the security mine field where no matter what option you pick you will piss off someone :)
As long as it's not Basic Auth I'll be happy I think.
One thing I worry about with requiring an API key is that Pownce may decide to attach metadata to that key and if so, then I will have to worry about sending my open source python code out to the world with a key that anyone can "borrow" and (mis)use for their own code.
For that case I would have to put a place holder in the code and put in very large print in the readme something telling them how to get their own key.
Yeah, I'm not really too hot on the API key idea personally. That's just one more thing for us to have to store in the DB, and another potential point of failure that we could easily avoid.
> On Jul 25, 10:48 pm, Shawn Allen <sh...@stamen.com> wrote: > ...snip... >> Aaaanyway... there's still a lot to consider as far as authentication >> goes. For now I think I'm going to punt on it and focus on getting >> the request/response formats hammered out so that you all can see how >> this thing's going to work.
> Sounds like a realistic path thru the security mine field where no > matter what option you pick you will piss off someone :)
> As long as it's not Basic Auth I'll be happy I think.
> One thing I worry about with requiring an API key is that Pownce may > decide to attach metadata to that key and if so, then I will have to > worry about sending my open source python code out to the world with a > key that anyone can "borrow" and (mis)use for their own code.
> For that case I would have to put a place holder in the code and put > in very large print in the readme something telling them how to get > their own key.
Like Ed, I'm quite keen on the Twitter approach to authentication. Easy to do with a curl request rather than messing around generating tokens and frobs and sending api keys etc which just becomes a hassle if you're doing things with multiple API's.
> Yeah, I'm not really too hot on the API key idea personally. That's > just one more thing for us to have to store in the DB, and another > potential point of failure that we could easily avoid.
> On Jul 26, 2007, at 9:54 AM, bear wrote:
> > On Jul 25, 10:48 pm, Shawn Allen <sh...@stamen.com> wrote: > > ...snip... > >> Aaaanyway... there's still a lot to consider as far as authentication > >> goes. For now I think I'm going to punt on it and focus on getting > >> the request/response formats hammered out so that you all can see how > >> this thing's going to work.
> > Sounds like a realistic path thru the security mine field where no > > matter what option you pick you will piss off someone :)
> > As long as it's not Basic Auth I'll be happy I think.
> > One thing I worry about with requiring an API key is that Pownce may > > decide to attach metadata to that key and if so, then I will have to > > worry about sending my open source python code out to the world with a > > key that anyone can "borrow" and (mis)use for their own code.
> > For that case I would have to put a place holder in the code and put > > in very large print in the readme something telling them how to get > > their own key.
> Like Ed, I'm quite keen on the Twitter approach to authentication. > Easy to do with a curl request rather than messing around generating > tokens and frobs and sending api keys etc which just becomes a hassle > if you're doing things with multiple API's.
> On Jul 26, 6:05 pm, Shawn Allen <sh...@stamen.com> wrote:
> > Yeah, I'm not really too hot on the API key idea personally. That's > > just one more thing for us to have to store in the DB, and another > > potential point of failure that we could easily avoid.
> > On Jul 26, 2007, at 9:54 AM, bear wrote:
> > > On Jul 25, 10:48 pm, Shawn Allen <sh...@stamen.com> wrote: > > > ...snip... > > >> Aaaanyway... there's still a lot to consider as far as authentication > > >> goes. For now I think I'm going to punt on it and focus on getting > > >> the request/response formats hammered out so that you all can see how > > >> this thing's going to work.
> > > Sounds like a realistic path thru the security mine field where no > > > matter what option you pick you will piss off someone :)
> > > As long as it's not Basic Auth I'll be happy I think.
> > > One thing I worry about with requiring an API key is that Pownce may > > > decide to attach metadata to that key and if so, then I will have to > > > worry about sending my open source python code out to the world with a > > > key that anyone can "borrow" and (mis)use for their own code.
> > > For that case I would have to put a place holder in the code and put > > > in very large print in the readme something telling them how to get > > > their own key.
I have been thinking about this for a couple of months now (building a similar API) trying to find the right balance between ease of use for developers to security and privacy. I am looking for 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 post assumes some people are not that familiar with all the current protocols and tries to explain it a bit (somewhat simplified). There are a 3 separate (but related) issues at hand: authorization, session management, and privacy. Each of the proposed solutions should be evaluated based on its impact on each issue.
Authorization
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, AuthSub, Passport, Facebook, 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 the 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 compatible with AJAX and other scripting solutions. It also requires maintaining state information about the auth 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 personally will not implement an API where service provides using my API gain access to user credentials. It is just too unsafe. 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. The following requires some knowledge of how OpenID works.
Each user will have a local username and password. I was trying to avoid it at first but with the current state of OpenID, it might cause problems as some OpenID Providers (OP) are unreliable and users can end up locked out if their only access is with the one OpenID they setup their access with. The plan is to provide an OP for local users (so that any local user is also an OpenID), and to also allow users to associate any other OpenID with their account. Once a user adds another OpenID to their account, they can use that to create a session via:
For example, a USER logs into a WEBSITE which is built on top of a web SERVICE. The SERVICE requires OpenID authentication. The USER login request is sent via AJAX to the SERVICE with a return_to URL able to capture the OP reply and send it back to the SERVICE. The SERVICE reply to the AJAX code with the checkid_immediate URL. The AJAX code calls the checkid_immediate given and captures the redirection reply. The AJAX code calls a second SERVICE API call providing the OP reply to the checkid_immediate request. The SERVICE validates the reply and answers with a SERVICE session. The AJAX code the stores the session id in a cookie and uses it for other API calls.
The same logic can be used with checkid_setup and a server side API call. The USER is redirected by the AJAX script to the checkid_setup URL received from the initiate API call. The user signs-in and is redirected back to the WEBSITE client_side_capture page with the OpenID query parameters. The WEBSITE server page client_side_capture receives the request, calls the SERVICE validate API, and redirects the USER back to the WEBSITE with the session cookie. In order to keep the transaction secure, I have added another signature to the return_to parameter. This way when the WEBSITE returns the OP reply to the API validate call, the SERVICE can make sure that the original return_to was created by it, and not by the WEBSITE. The normal openid.sig signature will make sure the OP reply is valid for the entire input. This is the an example API call and reply:
Once authenticated, most API allow using a session token (with or without expiration) to be used in place of constant authorization. Combined with an OpenID-like system, a user signs in and the client app gets a token to use for user-like access. Sessions also allow state-based API calls where an activity can be performed by a set of API calls with continuity. 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.
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 invalidates the token. This technique is vulnerable to IP spoofing but is usually good enough for more applications and easy 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 key. The key is received on a secure channel or is itself encrypted with a public key - the key is only known to the client. The client construct the API call (usually a REST URL) and then calculate a signature using the key. The signature is appended to the API request. When the server gets the request, it takes the signature off the URL, and then checks if the rest of the URL matches the signature. This proves the request came from the authorized user. To prevent reply attacks (someone grabs the API request and use it unchanged to make API requests), the client adds a nonce (number used once) to the API request before signing it. The server will only honor each nonce once from the client, so if captured by someone else, the server will refuse the call. Some implementations void the entire session/key when such a failed attempt occurs.
I have yet to make up my mind about using signatures for my own API. The question is, how big of a threat is IP Spoofing, and what's the worst case scenario if someone grabs a session. For example, if the sessions API (calls allowed during a session) exclude changing passwords and allows posting and reading messages, the damage someone can do by hijacking a session is low.
Privacy
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). My solution is the same, providing HTTPS access to users/clients wishing to keep their entire session private.
Would love to hear what other people think about this, especially about the idea of using OpenID as an API authentication platform.