Subject: [OAUTH-WG] OAuth abstractions

From: "Thomson, Martin" <[email-masked]>
Date: Fri, 22 Oct 2010 06:36:03 +0800

At the last meeting, I promised Blaine that I'd share a few thoughts on how I understood OAuth to operate.  It's taken me a while to find the time to marshal my thoughts, but here 'tis.

After attending the meeting and tutorial, it was clear that the abstraction behind OAuth is not being effectively communicated.  A simple abstraction can be a powerful tool in dealing with a complex specification.  It seems to me that OAuth struggles as a result of trying to cover so many use cases at once.  This might be easier if the abstract model were better understood.

I believe that OAuth has a very simple abstraction.  What I am going to try to do is describe that abstraction.  

The cunning techniques employed to circumvent technical limitations - redirection with URI fragments and so forth - are noise on the wire at this layer.  As a necessary product of having to reduce the abstraction to practice, they have little bearing on what I am going to attempt to describe.

I appreciate that the process is well beyond this airy-fairy stage.  If nothing else, I hope that this jostles a few brain cells into new ways of looking at OAuth.

To preface this with a warning: There's been a lot of discussion about the OAuth "protocol" and examination of its properties from the perspective of it being a thing that "uses HTTP".  There's a lot of HTTP experience that teaches the long term folly of trying to build on top of HTTP.  I'm probably going to beat on a dead horse by explaining where working _with_ HTTP (as opposed to _despite_ it) has significant advantages.

==First Abstraction

OAuth specifies a separation between authentication and authorization.

Never mind that HTTP got these mixed up early on, it doesn't now - HTTP only provides authentication.  The "Authorization" header is for authentication.  That might be implicitly used to infer authorization, but it's still fundamentally just authentication.

OAuth lets a Client come to a Resource Server with separate evidence for identity and authorization.

==Goal

A Client's goal is to acquire a resource from the Resource Server.  Or, to be more general, to successfully complete a particular type of (HTTP) request.

In order to do this, authentication is not sufficient, the Client must also prove that it is authorized.

The Client might be known to the Resource Server.  This is the authentication part.  There are existing mechanisms for that (the idea that these might be improved is a subject that comes up on occasion).  [1]

==Proving Authorization

Once the Client is authenticated (or not) the Resource Server might still reject the request.  There's an HTTP 403 (Forbidden) response for this purpose.

If this were at all like an HTTP 401 response, that rejection could provide the clues that could be used by the Client to determine how to acquire evidence of authorization (what OAuth calls the Access Token).  

I don't know if anyone has proposed this, but it seems logical to extend HTTP and work within its framework, thus:

  1. Add a header to the 403 (Forbidden) response.  This header would indicate that irrespective of the identity of the client, further evidence of authorization is required (that is, an Access Token).

  2. Add a request header that is intended to carry an access token.

The first might be a little complex.  Unlike the 401 response, OAuth has a number of variations on how an Access Token is required and this constrains the information that can be revealed at this point.  

This 403 header might include virtually no clues at all.  Maybe the equivalent of "realm" - some private identifier that helps those in the know distinguish between one set of authorization requirements from another.  What information is revealed depends on the desired security properties.

==Access Token

It's tempting to say that the Access Token is completely opaque to all but the Authorization Server and the Resource Server.  A private agreement between these parties could be used to determine what information is included.

In the abstract sense, the definition of the request header could just provide a bit bucket for a token.  In the macro, that's all the solution requires.

Obviously, the work doesn't stop there.  To ignore the access token entirely would be trivializing all the work that has been done in this area.  A separate authorization function is an important feature.  Structured agreements, such as the SAML assertions, have a significant role and formalizing formats can be extremely powerful.

Then there are the security concerns that arise when you wave your hands.  Saying "magic happens here" means that people create their own magic.  And that never really works out well.

So define two things:
 - how to acquire an access token
 - what the access token looks like, what data it contains, necessary bindings and so forth

The access token format is where you get into signatures and the like.  It also depends a lot on what the use cases are and the security properties that you desire.  I'm going to concentrate on the acquisition thing first and foremost.  The format should follow from that.

==Acquiring an Access Token

If the Access Token is view as an opaque lump of data [2], then there's an HTTP method that's well suited to this task: GET.

GET goes a surprisingly long way to accomplishing this task.

Say that the 403 response included - in the responses header, maybe a Link header - a URI.  That URI could be the URI for an Access Token resource.  Require authentication of the Client in order to successfully acquire the contents of this resource and you have dealt with the basic scenarios shown in Figures 2 and 3 of the -10 version of the spec.

This URI might not directly refer to the Access Token resource.  It could lead to a chain of HTML pages that need to be navigated successfully to get to the token.

The same basic abstraction also applies to the Access Grant.  The Access Grant and Access Token share a surprising number of common characteristics.  They both carry authorization information, independent of authentication.  The only difference is where they are acquired from.  An Access Grant is an Access Token for the Access Token resource.  Both are optional: the only difference being that if you don't use an Access Token, you aren't using OAuth.

What if the Access Grant and Access Token used the same mechanism?  Then you just have a chaining of the same process:

  Client goes to Resource Server, gets 403, 403 points to Authorization Server
  Client goes to Authorization Server, gets 403, 403 points to Resource Owner
  Client goes to Resource Owner, gets Access Token A (an Access Grant).
  Client takes Access Token A to Authorization Server with Access Token A, gets Access Token B
  Client takes Access Token B to Resource Server, gets resource

You could see how this could recurse.  

(It also occurs that you could also parallelize the process too and require multiple Access Tokens.  The analogy would be something like: "you must first collect the sword of Knorr, the sceptre of Manoth and the crown of Zaxx before you can claim the throne of Orion".  I don't know if this fits into the existing model at all, or even if it makes sense at all.)

==Other Stuff: Crazy Out of Band Ideas

That's really the core of the idea that I had, but there are a few things that I think are worth considering.

Implicit in my description is the fact that the entity that demands an Access Token (Resource Server, Authz Server) needs to know about the entity that produces it (Authz Server, Resource Owner).  I don't think that this is an unreasonable constraint.  The consumer of the Access Token has to know who produced it to check whether or not the Token can be trusted enough.

That could be used to push a number of things out of scope for the specification.  (Again, with due caution regarding the security properties - it might still be necessary to describe these uses, even if the on-the-wire formats aren't defined.  On-the-wire formats might still be part of external work.)

A lot of specification goes into specifying the things that are being exchanged between Resource Server and Authorization Server.  These could almost all be deferred to other specifications or only talked about from the security perspective.

For instance, the current request for an Access Token includes a client_id.  The reason for this is to ensure that the Access Token is correctly bound to a specific Client - so that another client can't use the token [3].  When it is assumed that the Resource Owner knows about the Authz Server, we can also assume that the Resource Owner is able to direct the Client to the Authz Server so that the Access Token it produces has the necessary bindings.

Another example is the redirect.  If the client follows the link to the Authorization Server, a Referrer header might be observed by the Authorization Server.  Once the Authorization interaction is complete, the Authorization Server could redirect back to the URI it first saw.  Alternatively, this information might be buried in the URI with the other junk, as described above.  There's no need to formalize this mechanism if the agreement is private.

E.g.
  Client goes to Resource Server, gets 403 response.  The 403 contains a URI that, along with identifying the Authorization Server, includes in an opaque portion that contains additional information: the client identity, the resource the client is trying to access, and other constraints.  The Resource Server knows how to construct this URI so that the Authorization Server can make sense of this.  By navigating to this resource, the Client ultimately acquires an Access Token - probably some sort of document with a media type that identifies it as an Access Token.
  Client brings the Access Token back to the Resource Server.  The Resource Server cracks that token open and checks it: is it valid? is it from an Authorization Server that I trust? is it for the current resource? is it for the current requester? is it valid right now?  If a check fails, the request is rejected; if they all pass, the request is permitted.

Formalizing the exchange between Resource Server and Authorization Server lets an arbitrary Resource Server use an arbitrary Authorization Server.  There are good use cases for this, but they are secondary to the function I describe above.  Separating that makes a great deal of sense.

==Other Stuff: Slightly Wacky Ideas

What if the resource that provides the Access Token provided the Access Token to any and all who asked?  That's not unreasonable if the token can only be used by an authenticated Client.

If the resource didn't exist until the Client was authorized, then that would make this more effective.

Or, maybe better yet, the resource might exist anyway, but the Client isn't told about the resource until they are authorized.  Anyone that knows the URI can use it freely, but only the authorized are ever granted knowledge of the URI.  The only condition is that the URI is hard to guess.  (See RFC5808 for a different application of this concept and a discussion of the limitations.  I'm also aware that this might have other issues in a web environment, because URIs don't stay secret with Referrer headers and the like.)

In this model, the URI and Access Token are interchangeable.  If you have the URI, you can give it to someone and that's just as good as giving them a token.  This might be useful for some of the more extreme use cases.

==No-so-thin Client

A lot of focus has been placed on using a client that doesn't understand OAuth for each of the use cases.  The use of redirection, particularly with URI fragments, belies this.  None of what I've suggested is impossible, it just requires that the Client have some control over the content of the HTTP requests that it makes.

That doesn't require explicit support from an HTTP client, just the ability to make requests and set the content of headers.  Such support has been table stakes for a long time.

Regards,
Martin

[1] Note that authentication is not strictly necessary, it might be sufficient to provide evidence of authorization as described in the counter-examples here: http://arstechnica.com/security/guides/2010/09/twitter-a-case-study-on-how-to-do-oauth-wrong.ars/2

[2] Copious caveats - as I mentioned, treating the Access Token as an opaque blob is merely a useful abstraction.  It gets you a long way.  Before you have to worry about specifics you can understand a lot about the goals and how those goals are achieved.

[3] It's interesting that the Access Token producer doesn't need to validate the client identifier.  As long as they aren't duped about who they are producing the Access Token for, they don't care that the entity that is asking is the same or not - only the consumer of the token needs to check that it is OK.

---

From: Torsten Lodderstedt <[email-masked]>
Date: Fri, 22 Oct 2010 09:44:56 +0200

Martin,

great to see you contributing to the WG!

One question came into my mind: How do the other grant types (assertion, 
username/password, refresh token) fit into your abstractions? The grant 
type used also depends on the client and its capabilities, so just 
returning a single URL pointing to an access token resource might not be 
suffice.

To give an example:

Alice stores her contacts at contacts.example.com.

She uses 2 clients, one on the PC and one on a mobile phone. The PC 
client uses the standard redirect-based process. The mobile phone client 
cannot use this process because of technical limitations (small screen 
size, sparse computing power, no integration API for embedding the 
browser or custom schemes). Therefore this client uses the 
username/password flow in order to get authorization and obtain a 
refresh token. The implications with respect to the flow:
PC client: redirect to end-user authorization endpoint
Mobile phone client: access to the tokens endpoint with the user's 
credentials

So although the resource server's URL is the same in both cases, 
different URLs will be utilized to process the authorization flow.

regards,
Torsten.

Am 22.10.2010 00:36, schrieb Thomson, Martin:
> _______________________________________________
> OAuth mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/oauth

---

From: "Thomson, Martin" <[email-masked]>
Date: Mon, 25 Oct 2010 14:00:16 +0800

Hi Torsten,

> returning a single URL pointing to an access token resource might not

The form of grant becomes a secondary concern.  Whether the resource owner provides a username/password, SAML assertion, or they just redirect to a secret URI, the process is the same.  

The resource owner passes information to the authorization server that says: this person who is making this request (optionally: who can authenticate that they are this identity) is authorized to access this resource (optionally: the resource is explicitly identified).  That resource in the context of your question is the access token; it's no different for the resource that is the goal of the whole thing [1].

> Mobile phone client: access to the tokens endpoint with the user's

Note that I'm still dealing with an abstraction at this point.  The fact that this information is passed via the client is the important concern, particularly for security reasons, because the client is a shifty, nasty individual that can't be trusted at all.

Ideally, the mobile phone client doesn't need to do anything any differently, other than (perhaps) provide a different UI.  

UI is the problem.  The real concern is the potential HTML UI that has to be navigated to grant/gain authorization.  The mobile can't cope with HTML, presumably.  If this were just HTTP, it would be no trouble.

The resource that provides the access token might be accessible using username/password alone (i.e. requiring authentication, but not explicit authorization), but as long as this is only HTTP, it's not a problem. [2]

> different URLs will be utilized to process the authorization flow.

Directing a constrained client to a different URL might be one way to solve the problem.  Another possible way is to use conneg: have the PC client send "Accept: */html" in the request to indicate that it's willing to tolerate HTML UI.  When the mobile client doesn't, it gets different treatment.

--Martin

[1] _THE_ resource.  Maybe this needs a special name too.

[2] I'll leave aside the point that a user might not trust the client with their username/password, but I guess that we can easily create temporary ones for this...

> > blah blah blah...