Existing OAuth 2.0 protocol explanations are riddled with terminology or tied
to specific implementations of the protocol. I'm mainly interested in
understanding what problem OAuth 2.0 solves and what the elements of its
solution are. In this article, I start with the scenario that you want
to give a budgeting tool like mint access to your transaction data
at Bank of America. I'll show the problems with the naive
approach and will gradually move toward explaining why OAuth 2.0 solves these
problems and how.
I gained my intuition from the book OAuth 2 in
Action which
has code-along examples if you want to see the OAuth 2.0 flow at work.
Login at Bank of America
On Mondays you check your transactions at Bank of
America to see the weekend's damages. You open up
your browser and you navigate to said site. You click Sign-in and are
presented with the classical login form. Full of anticipation, you enter your
username and password and get to see your poor monetary decision making. This is
the flow:
While a sense of dread sets in, we'll agree that I will refer to your
username/password combo as your credentials. To add to your existential crisis,
I'll shout at you:
OAuth 2 is not about credentials.
As if things did not start off bad enough, I will also identify you (aka the
human) with your browser, and will refer to you and your browser as one (in my defense, at
this point in human history, a fair assumption) and
officially name you and your browser, the User.
I'll call Bank of America, the Resource Owner: they own your
transactions (the resources). This how this story looks after dehumanizing it:
Use Mint to see your Bank of America Data
As you live in the illusion that life can be better, you want to start using a
budgeting tool like mint. mint allows you to pull in
your transaction data from a variety of resources. Bank of
America may be one of them, as could be your retirement
accounts at Vanguard, or your stocks at Morgan Stanley. In this
scenario, mint needs access to the Resource Owner (Bank of
America, Vanguard, ...) on behalf of you, the User.
The first approach that comes to mind to make this access possible is to let
mint ask you for your credentials and pass them straight through to
Bank of America whenever mint needs transaction data:
I'll call mint the Client in this scenario, such that the
general scheme looks like this:
Of course, mint asking you each time for your
credentials is unpleasant. So mint might
be tempted to think we'll ask you once, and then we'll store it so we don't
have to ask you again.
The flow looks exactly like above, except that now mint asks you
for credentials once and then stops asking you as they now store them.
What are the problems with this approach?
the client stores your credentials. If mint gets compromised and your credentials get stolen, someone else now can access your Bank of America account. You have the same problem with Bank of America itself getting compromised, but this scenario increases your risk with a factor of 2 (from 1 place that has your credentials, to 2 places that have your credentials). With each additional client, your risk goes up.
anyone with your credentials has the same access you have. Depending on what you can do as a user, someone having your credentials can do exactly what you can do. Whereas you want mint to see your transactions and categorize them, you would not want mint to able to transfer money. However, someone with your credentials from mint could exactly do that.
We're thus looking for a solution where:
the client gets read-only access to your transaction data without having to ask you each time for your credentials, aka the client can get the data on your behalf
the client does not store your credentials directly as this is unacceptable risk
OAuth 2.0
OAuth 2.0, a delegation protocol, solves exactly the above. It's named a
delegation protocol as it concerns itself with the on your behalf part in
the above: how can you, the User, delegate Resource access to the
Client without that it exposes you to unacceptable risk? We leave it as an
exercise to the reader why the name is OAuth and not ODel.
The Players
So far we identified 3 players in the OAuth 2.0 delegation protocol:
the User: you, or a proxy for you, like your browser
the Client: the application you're interacting with and you want to delegate your access rights to, for example mint
the Resource Owner: the origin of your data, for example Bank of America
OAuth 2.0 introduces a 4th player for the actual authorization:
the Authorization Server.
In our running example, I'll assume the authorization server is owned by Bank
of America, a logical choice as Bank of
America is the one that can verify your credentials
directly.
The Dance
Given such an authorization server, can we instruct the client to delegate
authorizing you to the authorization server? If yes, the authorization
server can then verify your credentials and inform the client that yes, you
can give that user access to the transaction data.
What are the elements of such a delegation? Let's see:
the client (mint) needs to send you, the user (or your browser), to Bank of America's authorization server
the authorization server needs to verify your credentials and needs to conclude yes, you have access
the authorization server needs to tell the client that the particular user has access and can get the data from the Resource Owner.
the client needs to take that authorization to the Resource Owner to ask for the user's data
Each of those elements can be accomplished as follows:
sending the browser to the authorization server can happen using an HTTP redirect (code 301). The user wants to access the data from the client, but the client instead sends the user's browser a redirect to the authorization server. The browser subsequently follows that redirect and lands at the authorization server.
the authorization server then starts an interaction with the user's browser to get and check the user's credentials
the authorization server can tell the client that the user's credentials are OK by similarly redirecting the user's browser back to the client by including in the redirect URL something called an access token.
the client would then use that access token (which it keeps associated with the user) to go and ask the Resource Owner for the user's data. Since the Resource Owner is presumably able to interpret the access token (both the Resource Owner as well as the Authorization Server are Bank of America), the Resource Owner can verify that the access token is indeed valid.
That flow looks like this:
Or abstractly:
Recall that we had the following problems with the naive approach:
the client stores your credentials
anyone with your credentials has the same access you have
Let's see whether this new flow solves those problems:
The client indeed no longer stores your credentials. The client stores the access token, not the credentials. How is that different from storing credentials? The access token has been provided by the authorization server and is assumed to be unique for the client. Thus, when your access token is stolen from the client and used by someone else, the Resource Owner can verify that the access token does not belong to the right client. Furthermore, once access tokens are stolen, the Resource Owner could disable all access tokens for the client and ask all users to authenticate again. A client being compromised would not affect you, the User, to get data from the Resource Owner directly (i.e., by logging into Bank of America directly).
Someone with the access token does not have the same privileges as you have at the Resource Owner. We left that out of the above discussion but clients would redirect you to the authorization server specifically asking for a certain scope of access (read-only access to certain parts of your data for example). So even if someone can use your access token, they would be able to do only what the scope for that access token allows them to do (which would presumably not be to transfer money or change your original credentials at Bank of America, but just use your transaction data, which is bad, but not as bad as having the full access you have).
That was not too complicated. However, there is one problem with this access
token flow as it is right now. Can you spot it?
Let's zoom in on the interaction between you, mint, and the Bank of America authorization server:
As we explained above, this interaction happens mostly via HTTP redirects over your browser:
the authorization server sends your browser a redirect with the access token in the URL or body
the browser hits mint with that access token in the URL where mint stores it and uses it to gain access to the resource (Bank of America)
The problematic part here is the browser. This part of the communication, the
back-and-forth using redirects, is called the front-channel communication and
since it goes via your browser it is vulnerable to having the access token
intercepted. The back-channel communication (for example, from mint to the
Resource Owner) is much more secure in that respect; there is no user browser
involved, just service to service communication.
The way OAuth 2.0 deals with this is to have the Authorization Server not
redirect you to the client with the magical access token, but with an
authorization code grant instead:
The front-channel no longer sees the access token. It does see the
authorization code grant. What if that authorization code grant gets stolen? Can
the thief access our data at the Resource Owner with that information?
The authorization code grant does not give you access to the data at the Resource
Owner as the Resource Owner needs an access token. Can the thief get an
access token from the Authorization Server given the authorization code grant?
The getting of the access token happens on the back-channel from the Client
to the Authorization Server and as such can be protected (no User involved)
by requiring the Client to send a client id and client secret which the
Authorization Server can verify.
Conclusion
We illustrated two problems with giving your credentials to a client such as
mint directly:
the client stores your credentials
someone that steals your credentials has the same access you have
We gradually introduced the OAuth 2.0 flow (The Dance) that solves these
problems, moving from an incomplete solution with just an access token to a
solution with both access token and authorization code grant.
In order to convey the basic intuition (the why of OAuth 2.0) we left out
many parts such as the different types of authorization code grants, the
particular format of access tokens, what refresh tokens are and where they come
into play. If you're interested in learning more check out OAuth 2 in
Action or,
better, implement OAuth 2.0 yourself to secure your service.