Elements of OAuth 2.0

Elements of OAuth 2.0
Stijn Heymans
published: 30 January 2020
last updated: 23 February 2020
Introduction · Login at Bank of America · Use Mint to see your Bank of America Data · OAuth 2.0 · Conclusion

   

Introduction

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:

YouBankOfAmericamyusername/passwordyourtransactions<----------YouBankOfAmerica

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:

UserResourceOwnercredentialstransactions<---------UserResourceOwner

   

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:

YouMintBankOfAmericacredentialscredentialscheckcredentialstransactions<---------transactions<-------YouMintBankOfAmerica

I'll call mint the Client in this scenario, such that the general scheme looks like this:

UserClientResourceOwnercredentialscredentialscheckcredentialsdata<----------data<--------UserClientResourceOwner

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?

We're thus looking for a solution where:

   

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:

OAuth 2.0 introduces a 4th player for the actual authorization:

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:

Each of those elements can be accomplished as follows:

That flow looks like this:

YouMintAuthorizationServerBoABankOfAmericashowmytransactionsIcan't.I'llredirectyou<-------------givemintaccesstmytransactions|givemeyourcredentials<--------------------------|credentials|checkcredentialsOK.redirectingyoutomintwithanaccesstoken|<--------------------------showtransactionsgiventheaccesstokenhere'stheaccesstoken.givemedatacheckaccesstokentransactions<--------------------------transactions<-------------YouMintAuthorizationServerBoABankOfAmerica

Or abstractly:

UserClientAuthorizationServerResourceOwnergetdataIcan't.I'llredirectyou<-------------|IwanttogiveClientaccesstodata|givemeyourcredentials<-------------------------|credentialscheckcredentialsOK.redirectingyoutoClientwithanaccesstokengetdatawithaccesstokengetdatawithaccesstokencheckaccesstokendata<-------------------------data<-------------UserClientAuthorizationServerResourceOwner

Recall that we had the following problems with the naive approach:

Let's see whether this new flow solves those problems:

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:

YouAuthorizationServerBoAMintcredentials|checkcredentialsOK.redirectingyoutomintwithanaccesstoken|<------------------------showtransactionsgivenmyaccesstokenYouAuthorizationServerBoAMint

As we explained above, this interaction happens mostly via HTTP redirects over your browser:

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:

UserClientAuthorizationServerResourceOwnergetdataIcan't.I'llredirectyou<-------------|IwanttogiveClientaccesstodata|givemeyourcredentials<--------------------------------------credentials|checkcredentialsOK.redirectingyoutoClientwithauthorizationcodegrant|authorizationcodegrantgetaccesstokengivenauthorizationcodegrant|checkauthorizationcodegrantyouraccesstoken||getdatawithaccesstoken|checkaccesstokendata|<--------------------------------------data<-------------UserClientAuthorizationServerResourceOwner

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:

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.

formatted by Markdeep 1.18