有趣的 oAuth2 OpenID Connect
I’m not a deep OAuth 2.0 expert yet; at this point that label is reserved for the (substantial number of) people who wrote the specs. But I’ve worked with a few implementations and talked it over with smart people, and I have opinions. Summary: It’s a framework not a protocol, it has irritating problems, and it’s really very useful.
Real Internet Protocols · I mean things like HTTP and SMTP; plug a client and a server into each other and if it doesn’t Just Work, that’s surprising. ¶
OAuth 2.0 isn’t one of those; the language of the spec is full of “Out of scope” and “At the discretion of the implementor”. It’s not that a generic OAuth2 client might not interoperate with a generic server; it’s that there’s really no such thing as a “generic OAuth2 client” or “generic Oauth2 server”.
So, is it really a “Standard” in any useful sense? And should we invest in implementing it? Yes to both. OAuth2 is, for lack of a better word, a frameworkthat you can use to build actual real protocols.
For example, Google has an authorization protocol for accessing its APIsthat’s totally OAuth2. It meets our security needs and it’s been easy for us (and anyone else) to ship libraries for app builders to use, because there are starting to be common bits and pieces of framework implementation to use. And also because OAuth2 just isn’t that hard.
Another example would be OpenID Connect, OIDC for short. It’s trying really hard to be a real actual Internet Protocol; plug a client into a server and feel entitled to anger if it doesn’t Just Work. I’m super-interested in OIDC and starting to become a fan. In fact, it deserves its own space in ongoing, so let’s note that it’s built on OAuth2, push it on the stack, and return to it in another piece.
What OAuth2 Actually Does · Let’s work through it from back to front. The end-game of an OAuth2 invocation is an “Access Token”, just a string of characters.
It’s called a “bearer token”, which means that you send it along with an HTTP request, either using the HTTP
Authorization header (which is the right way) or as an
pair tacked onto the end of a URI (which makes me nervous, and I wish people wouldn’t). ¶
Anyhow, the token represents the right for you to make that HTTP request to whatever the URI identifies. The tokens are fairly short-lived (an hour or less is typical) but can be refreshed. They can also be invalidated, in which case they stop working. For example, the string
was an access token that for an hour sometime last month represented the right for email@example.com to access the Google+ API.
OAuth2 also specifies how you go about getting a token; it’s a fairly involved HTTP dance involving several distinct servers, notably including:
One hosting the resource you’re trying to access,
one that can authenticate the person logged into the browser making the request, and
one that can issue and refresh the actual tokens.
Yes, it’s possible for some of them to be the same server, but whatever. The way it works is that the first redirects to the second redirects to the third and then you go back with your token to the first and do the actual work you started out trying to do.
The OAuth2 specs lay out how to build the target and redirect URIs and code the parameters and so on. They also specify that the app launching the dance has to be registered with the server-side logic in advance.
Anyhow, turn all those cranks and your token comes out of the machine and you’re off to the races. That’s about all there is to it; but it takes a whole lot of pages of specification-ware to describe all the pieces.
What’s Wrong With This Picture? · OAuth2 is controversial; the spec editor eventually got mad enough to stomp out of the room, and is now off in his own sandbox writing his own replacement for OAuth2. He (and others) have said these things about it: ¶
The spec suffers from enterprisey bloat; it’s too big and too complicated and can only be implemented by leviathans.
The notion of naked bearer token is insane; anyone who can eavesdrop on your HTTP conversation has the keys to the kingdom. The tokens need to be signed and/or encrypted and thus immune from tinkering.
The OAuth2 dance depends on Web-browser semantics with all those redirects, and thus isn’t really suitable for compiled mobile (as in iOS and Android) apps.
I think they’re all problems, but only one of them really costs me lost sleep. Let’s take them in order.
Is OAuth2 Too Big? · Yes, absolutely. It’s got way more stuff in it than, for example, an Internet company like Google needs; mostly things that are there to meet professed Enterprise requirements. The Working Group clearly needed more irritating loud-voiced minimalists stridently chanting YAGNI! YAGNI! YAGNI! ¶
The critics are right that it would be a big engineering challenge — maybe impossibly big — to build a quality implemention of the whole thing.
That doesn’t bother me as a Googler because I don’t think we’re going to try. We’ve built the parts of the framework we need to implement the protocols that we want to support, and I can’t see us caring much about the rest.
This is a time-honored practice among implementors facing over-ambitious standards (which a majority of standards are).
I’m pretty convinced that there’s a 80/20 point there inside OAuth2 that provides real value and is pretty tractable to implement. It might make sense, with a couple years’ experience, to write that subset down and give it a name.
Are Bearer Tokens Sane? · No, unless you encrypt your transport, in which case they are. I start with a bit of a prejudice here, since I think thatall Internet traffic should be private by default, i.e. be conducted using HTTPS. ¶
It’s like this: If you’re sending data that needs authentication/authorization back and forth over channels that are subject to eavesdropping, stolen bearer tokens are going to be the least of your problems.
I acknowledge my prejudice; but my convictions are reinforced by the fact that Google’s security gorgons, who are an exceptionally paranoid bunch of people, are OK with bearer tokens too.
Also, while I never worked with an OAuth 1 implementation, I sure heard lots of complaints about how hard it was to get the encryption and signing to interoperate. I have worked with several OAuth2 services and it’s no biggie. People I respect say that in principle OAuth 1 shouldn’t be hard. Maybe it’s simply that OAuth 2 has had better libraries ship faster than its predecessor?
At this point, cue whining from people who say they can’t HTTPS because they need to do deep packet inspection for reasons of load balancing or regulatory compliance or whatever. I think they’re mostly just Doing It Wrong, but if the bottom line is those people can’t use OAuth2, well OK.
How About Mobile? · Yeah, it’s a problem. People who use Google apps right now on iOS know all about it; you’re always having a browser pop out at you and you have to type in your password way, way more than you should have to, which on a mobile device is basically never. (Yes, we know that we need to do something about this.) ¶
We’ve worked around it on Android and made it easy for apps to get OAuth2 bearer tokens, but we had to build great gobs of Android and back-end code that bridge across lots of different pieces of Google infrastructure and were a major pain in the butt to debug; I know because I helped.
But what we got provides a pretty decent outcome; you can use Google’s APIs, and authenticate users to your own back-ends, with good performance, good security, and really rather nice user experience. I don’t see any reason why anyone else shouldn’t be able to do the same.
So maybe, even though OAuth2 isn’t a great fit for mobile apps, the cost/benefit analysis is such that we server-side folks should just suck it up and build the back-end code to make it work.
Having said that, I’ll take a good close look at anything that promises to make life easier for mobile-app writers.