From many conversations that I've had with people over the past few
years, it's been clear to me that there's a significant amount of
confusion about the state of interoperability in OAuth. All notions of
profiles and deployments aside, I believe that many people have
different ideas about *what* exactly is meant to be interoperable within
OAuth, and these expectations lead to premature declarations of OAuth
being non-interoperable. The truth is that there are a lot of moving
parts in OAuth and different parts of the protocol family deal with
interoperability between different pieces. I'm going to attempt, here,
to lay out what I see as the fundamental interop concerns that each
component deals with, and hopefully this can help drive the conversation
forward in a constructive manner:
RFC6749: client <-> AS
The core spec deals with interop between the client and the
authorization server, in four different flows that tell the client what
it needs to do to get a token. (Five if you count refresh tokens.) The
resource owner/user agent are used as mechanisms to facilitate the
interaction between these parts, but they are by and large passive
carriers of the information being passed along the front channel. It's
important to realize that RFC6749 doesn't say anything about
interoperating with the protected resource. It's also important to
realize that RFC6749 doesn't say anything about interop between the
resource owner/user agent and the client, or between the resource
owner/user agent and the AS. The core is, by design, silent on these
matters.
RFC6750: client <-> PR
The bearer token spec deals with interop between the client and the
protected resource by defining one kind of token and telling the client
how to use it at the PR. In defining the token type, it does define what
would is returned from the AS. This, however, I think is an unfortunate
artifact of the core not defining an abstract object structure
representing the token, and instead defining only the JSON serialization
coming from the token endpoint's output (which is then serialized in
parameters in the implicit flow, and maybe we can fix this all in OAuth
2.1, but I digress). However, the core of this spec is to tell the
client what to do once it gets a token. Ultimately, RFC6750 doesn't care
how you get a bearer token, and we've seen many instances of issuance of
bearer tokens that don't use any RFC6749 constructs. But once you get
that token, and it is a bearer token, then a client can use RFC6750 to
hand that to a protected resource. RFC6750 is also silent about what the
protected resource does to figure out what the token's good for, or if
it's any good at all.
JWT, Introspection: PR <-> AS
Since everything to this point has been completely hand-wavy about how
the heck a PR and an AS can agree on what to do with a token, these two
specs (and their associated ecosystems) solve it in different ways. Of
course, the most common approach, and the one assumed in OAuth 1.0, was
that the AS and PR were actually the same thing. But since we can
theoretically split these two in OAuth 2.0, we need some means to get
them talking. JWTs pack information into the token itself, building
directly on top of RFC6750's bearer token (for the most part), and use
JOSE to provide different flavors of protection and assurance. A common
pattern with JWT that I've seen is to have something that can facilitate
service discovery in the "iss" field (like a URL), and then
asymmetrically sign it with the AS's key so that the PR can check the
signature. Then everything in the token can be used to figure out
important things like who the token's for and what it should be used
for. Introspection uses a web-API approach to solving the same problem,
where the PR makes an HTTP GET and passes the token along back to the AS
to get this information. Both have their benefits and drawbacks and can
even be used together (ie: parse the JWT to find the issuer, then call
introspection on that issuer).
Then you have things like Revocation which deal with token-holder <->
AS, where token-holder can be either the client or the PR depending on
what's trying to be accomplished. Registration deals with client <-> AS,
resource provisioning deals with PR <-> AS, and of course there's UMA
which connects everybody to everybody else by using most of these
components in a single, comprehensive application of awesomeness.
Where have we gone awry on this? For starters, current revision of the
signed token spec attempts to solve both client <-> PR and PR <-> AS
interoperability simultaneously, and I think that's a mistake. There are
also those who assume client <-> AS and client <-> PR interoperability
as indivisible from each other, which is also a mistake. And then there
are those that see that one spec or another doesn't specify interop
between all points on its own, so they conclude OAuth is fundamentally
non-interoperable. This is a grave mistake but it's a very real problem
of perception that OAuth has in the real world.
I think that as we go forward with OAuth interop testing and continued
profiling, we need to keep in mind *what* is interoperating with *what*
for each piece that we care about.
-- Justin
_______________________________________________
OAuth mailing list
OAuth@ietf.org
https://www.ietf.org/mailman/listinfo/oauth