I was recently tasked with learning and developing OAuth 1.0A and 2.0 servers, and it got me thinking about the use of OAuth when dealing with loosely coupled systems and software as a service. Having completed the task of writing an OpenID Server in the past, after I completed work on the OAuth server, I think I finally have a really firm understanding of the true differences between authorization vs. authentication. Given this, I imagined OAuth and OpenID as the central hub for authorized activities in a series of loosely coupled systems, but the difference between the two and what they do was incredibly difficult to integrate in my head. My local application would have additional capabilities saying that it really didn’t need to get authorization to get access keys, where as any other application would be forced to. This appeared to require additional capabilities, but I think that there might be a way to do this, and the only thing that I would need to remove is the authorize page for auto authorized applications.
Either way, I’m going to talk through a process flow really quick and push this out into the world. If you don’t already know what OpenID and OAuth are, then you should go out and get some understanding. I’m going to expect a lot of knowledge of their process flows from the get go. I’m not a fan of OAuth 2.0, so most of what I’ll discuss is 1.0A (this is mostly security complaints, non-signed bearer tokens scare the living daylights out of me).
Here is an image that might be able to describe what I’m thinking a bit better than a bunch of words.
All of this follows a very normal web flow. First, you have login which uses OpenID. This is very standard, and I use this all over the place. It gives you an actual identity. OAuth, by default, does nothing of the sort – it is for authorization, not authentication. Now, normally, for any external web application, having the authorization and authentication completely separate is fine. Note that even in my diagram that Login and Authorization flows are completely separated. They should be, as they are two separate activities and ideas. Authorization gives you a token that represents ‘someone’, but you actually have no idea who that is, other than they are authorized and connected to your application and probably to a user id that you are keeping internally. You might have service availability that gives you information about the resource attached to that token (for instance, in Facebook Graph, that would be ‘/me’), but that comes after the fact.
This creates a conundrum – how do I force the attachment between a logged in user on my side, and the OAuth token that I will receive from the Authorization server as well, without extending OAuth (because I want to make my stuff available to non-internal applications eventually). You could argue that this is all overkill for a little app that I’m writing myself, but this is a really good standard way to make pieces of your application tie in together and to make it so that you could easily give OAuth OR OpenID for external application usage.
Connecting Authorization and Authentication
I was trying to find ways to connect these things together, and I think that one possible way to do so is to have multiple OAuth endpoints – some representing specific users. The identity that you return via OpenID could be used as an OAuth endpoint given the state of parameters or the authorization header sent that is typical in OAuth requests. Using this, you could enforce authorization by a specific user without actually extending the OAuth protocol.
At this point, I would like to make clear that this is only really feasibly secure via the OAuth 1.0A standard as defined. One problem solved in 1.0A not solved in 2.0 that breaks this is that you could change the url that you are directed to in 2.0, which would be hugely problematic especially if for your own web application you were hoping to avoid the authorization screen (essentially auto-authorize, which could be an application capability you could attach to application keys – but that you would attach only to your own). Since 1.0A has a standard way of signing which includes the URI base in the string it supplies to the digest, trying to gain the capabilities of another user by changing the base URI would result in failed signature verification. This type of signing, and the nature of the strings supplied to the signature hash, are a perfect example of why OAuth 1.0A is superior to 2.0.
With that out of the way, you could logically build an app that first requested an OpenID Identity from the authorization server. Let’s say that the identity returned was
“http://www.paulsalcido.com/user/paulsalcido”. Using a properly developed OAuth endpoint, and with an application key for my personal web application that included an auto-authorization capability, I could get my request key and redirect to the endpoint “http://www.paulsalcido.com/user/paulsalcido”, where, because it had oauth parameters or headers, I could require that the user represented by the identity become the logged in user, then either get authorization or skip it for auto-auth application keys (auth is all up to the server implementation anyhow).
Now, if you were to code your entire code base using the OAuth model with SaaS, then opening up either a) OpenID and/or b) OAuth is incredibly simple, especially if you have a non-OpenID identity OAuth endpoint (for instance, http://www.paulsalcido.com/oauth/, etc.). External applications would not have the same need of attaching OpenID and OAuth together – only your internal application where it is expected behavior of a primary web application interface.
I don’t know if this is SOA overkill, but thought it would be something interesting to mention because I’ve been thinking about it a lot.