OAUTH 2.0 Explained Like You Are Five
In this article I will define and elaborate on OAuth 2.0, List of Grant types, and their technical work flow. This is four pages long, so going to be a very long read so get ready.

By Omkaram - Mar 10th, 2024



What is OAuth 2.0?

OAuth 2 has become a buzz word over the past decade and more and more people, companies are using to it. But the way, most people do not realize that they are already using OAuth unknowingly on daily basis. So what is OAuth?

OAuth as the name dictates is short form "Open Authentication". It is simply an Access Delegation Authorization Framework which helps users to grant access to the resources they own to any consumer without providing the credentials such a username and password.

But before you fully understand OAuth you must first understand the difference between Authentication vs Authorization.


What is Authentication?

In simple words, Authentication is the mechanism which helps to identify who the User is. When I say "User", I am not just referring to Humans. Anyone or anything which wants to use a resource can become a User. Often because the word "User" conflates with the idea of "Human", some people lately started to address "Users" as "Consumers". Consumer can be people, apps, companies etc. An application which work on behalf of a human is called User-agent. Example User-agents can be Postman, browsers etc. Instead of using the word "User-agent" over and over, I simply refer to it as the User. Over the course of this article, I use the word "User" several times and I can be referring to a Human or software depending on the context. But this is trivial.


What is Authorization?

This is a mechanism in which the system is trying to validate whether an already Identified User is Authorized to access a particular resource or not. The word "resource" here again can be anything, such as a file, program, data etc. For example, all the employees of your company are aware who you are and how long your have been working there. They trust your Identity as a person, but when it comes to accessing certain files or programs, they do not trust you, because you are not the right person to access that thing in question. Hence you are not Authorized.

But here is the Catch. If you remember what I said in the beginning, I said OAuth is an Access Delegation Authorization Framework. Well, to access something means you must Authenticate first. And to access the same thing you must also be Authorized. Which means All Authorizations are mandatorily Authenticated. Imagine a situation where you do not Identify a person (basically did not Authenticate him or her) but granted than access to the protected resources. That would be a disaster right? So you can say All Authorizations are Authenticated, but not Authenticated are Authorized.

Now let's talk about OAuth, especially we will talk about OAuth 2.0.


How OAuth 2.0 Works?

Before OAuth version 2 came to existence there was OAuth version 1. The thing that differs between these two versions is, in Version 1, there is the concept of a User, a Service Provider and a Consumer and there is not explicit boundaries between the roles of Authorization server and Resource Server. In OAuth version 2, the User became the Client for namesake, the Authorization Server and the Resource Server stayed, and there is the Resource owner. So far I haven't yet explained to you what these terms means, so please bear with me. OAuth in it's core boils down to just a few words "The owner wants to access a protected resource via a third party". One thing to remember is Version 2 is not backward compatible with Version 1 due to the difference in roles and philosophy.


Let's create a Scenario

Imagine you have a Facebook account and you have a bunch of beautiful pictures uploaded in the images section. Later, you have come across some new trending Website called "TinyBell" and you want to immediately move your images to TinyBell. Now, you can do it two things here. If you have patience and time, you could download the uploaded images onto your machine, and then re-upload to TinyBell. Now imagine if the world is inventing a 100 different websites every year, and this time you don't want to just move your pics but also some bio data about you that you have on Facebook. You must have realized by now that as the number of Consumers applications you use grow, it gets difficult quickly and you will get frustrated and stop using all of them. The same case applies for Password based Authentication. If you are coming across several new and trendy websites, you have to create an Account with all of them first, but that means you have to specify a Username and Password for each Website. You may try to get away with this hassle by just using the same password of Facebook in all of your new accounts, but guess what, if one of these websites is compromised, then all of your other accounts are also doomed.




OAuth comes to rescue

So, you have decided to not manually upload the photos and bio data into each website and wondered if Facebook can share the data to the them automatically during the time of creation of a new account with them. Now, instead of sharing the same username and password of your Facebook account with TinyBell, if TinyBell already trust Facebook as a legitimate entity for information, account validity and identity, then TinyBell could just make a request to Facebook requesting for the pics and bio data on your behalf, with your awareness and permission and get the results. This way TinyBell need not create a dedicated account section for you as long as you have an account with Facebook, because Facebook has become their Trusted Service Provider.


The way this is achieved on a high level is what I will explain now. This is called the OAuth flow or OAuth Dance.

  1. Firstly, TinyBell the company has a web app and it is considered as your Client. Now, most modern web apps work on client side, an example could be an WASM app. But there are server side rendered web apps and all your browser need to do is to display html and css. In this scenario we will be playing with, the TinyBell's web app is server sided. This is important.
  2. You, the user is the Owner of the Resources in Facebook. Hence Facebook becomes the Resource Owner.
  3. Now, TinyBell's web app may or may not trust Facebook as a legitimate OAuth service provider. But just to simplify things we can assume that Facebook is already trusted and they have decided to use the Facebook Authorization API to start the flow. If so, Facebook also becomes the OAuth Service Provider along side being the Resource owner. In the real world, this may not be true always. Your Resource owner can be one entity and your OAuth service provider who serves the web app the Authorization endpoint can be another entity.
  4. Nevertheless, all Service Providers must have an Authorization Server with them. They help generate access tokens and provide these tokens to the Client, in our case TinyBell's web app. From now on let's just call it simply "The Web App" or "The Client".
  5. The web app can request for access token to the Authorization Server after authentication. The fetched access token will be posted to the resource Server for validation and giving the web app the final account access to do things on the resources provided by the scope.
  6. Note: Here the Authorization Server does not provide valid access token to any Client just like that. To fetch an access token , the client needs to Authenticate and for that there are Authorization Grant types and that's a complex topic on its own. Also, in this whole process we have to go with the blind assumption that the trust is already built between the Resource Server and Authorization server. Without that having access token with you and passing it doesn't mean anything to the Resource server. If what I have explained so far is good enough, then great, you can exit this page and be happy for knowing Oauth on a very high level.

Want to learn in Depth? keep reading.

Now let us understand the OAuth flow in depth. Once again, here the client is you and the TinyBell's web app, Facebook has an Authorization server and a Resource server. There are two categories of access tokens which are fetched by the client. It the request is being made by a web app using a browser that takes one procedure, but if there are is no browser support such as your client is a native app then it takes a different procedure to fetch the token. In this scenario our web app is using a browser. This is where the concept of Authorization Grant types appear. In OAuth a grant type is basically the list of possible mechanisms a client requests the Authorization Server an access token. There are basically 6 popular different grant types employed.

  1. Authorization code
  2. Client credentials
  3. Password credentials
  4. Implicit
  5. JWT based
  6. Refresh token

Authorization Code Grant Type

Authorization code is the most popular one, and also the most complex one to implement in infra, which is why we will be looking at first. For this grant type to work, the client must have browser support. Also, this grant type has to do some extra steps when compared to implicit and client credentials grant types.

This process is called the Authorization flow. Regardless of the grant type, OAuth is focused only on providing the clients with limited access.

  1. The web app on its login page loads the Facebook's login page on your browser. Note that the web app is actually rendering on a server of TinyBell's. When a User like me and you enter our username and password and hit the submit button, the flow control is given to Facebook and Facebook authenticates you, and give the control back to the web app. This process of Authentication is not covered under the OAuth 2.0 specification. What this means is, OAuth 2.0 does not care how the Authorization server first Authenticates it's user and it's beyond its scope.
  2. Now web app makes a new request implicitly without any user intervention to the Authorization server with the permissions it needs. The web app in our case decided to use the Auth Code grant type and hence it passes the ?response_type=code in the query parameters of the url Authorization url. It also defines a "scope", which tells the Auth Server for what operations the access token is being requested for? For simplicity sake, let's say the "scope=access_user_photos". Next, the web app provides a redirect uri and a state in the query parameters. The redirect_uri defines where to send the Authorization code when the User approves the request to grant an Auth code. The redirect _uri will always be tied up to the application/client web app you are using. Usually, there would be some service listening on a host and port on the web app server. The "state" parameter is a random string passed to prevent any CSRF attacks by later cross verifying if the initial state text is the same as the one which comes from the Auth server using the redirect uri.
  3. So far, the web app has formed a Authorization url with the query parameters such as state, redirect_uri, scope, and code. But there is one parameter which takes the prominence in this http call, and that is the client_id. The client id is a string which is passed to the Auth server by the web app from your browser itself to show that it requesting the Auth code for a specific user. Without the client_id the Auth server will not be able to recognize which web app is requesting the service. This client id is something which the web app server generates and provides to your browser for initiating the Auth flow. On the contrary to popular belief, a separate client id is not granted to each user which is trying to create an account with the web app.

    The web app is just one client and so there will be only one client id and client secret used for all the users of the web app. I will talk about the client secret when the time comes. Well, you must be thinking, if the Auth server already identified you "the user" during the initial Login page authentication, why does it need a client id again to validate the user? Well, the Auth server is not trying to identify the user or the browser, it is trying to identify for which service the user is approaching it for an Auth code. By seeing the client id the Auth server is able to recognize that the user is trying to request for an Auth code for the Web app TinyBell. So you see the Client (TinyBell's web app) need to first register for using the OAuth facility with Facebook, collect the client id and client secrey Facebook provides and place it in the web app server configuration to hand over the client id to user browser which will be making the OAuth calls. So client_id=273628e182a272805b goes in the query parameters.


                                        
    https://www.facebook.com/authorize?
    response_type=code&
    client_id=273628e182a272805b&
    redirect_uri=https://tinybell.com/callback&
    scope=access_user_photos&
    state=randomstringxyz95829
                                          
                                    

  4. The request goes to Facebook and since it already Authenticated you in very first login page step (where it already loaded some session cookies in your browser), it checks your cookies, the client_id, identifies your web app, see the scope for which the web app is wants the permissions, sees the response type and understands that the web app is asking for a Auth code, sees the redirect uri and responds to the current live page in the webapp in your browser with a prompt asking for your permission to allow this action with an Approve button. If you click "Approve" the call goes back to the Auth url and the server, sends an Auth code to the browser. The Auth server not only send you the code, but also tells you the redirect url, which the client app already registered.
  5. A "state" parameter which is given to the browser by the web apps is also returned in that request.

We have now completed the Authorization flow, but there is still a lot to this grant type. Keep reading.



Here is a critical point to remember. Even though your browser is passing a redirect url in its request to the Auth server, the Auth server is not guaranteed to use it. The Auth server implicitly does not trust you or your browser. Well, it depends on how the Auth server service is setup. With some Auth servers you don't have to pass an redirect url in your Auth code request and in some you have to provide one. Whether the server uses it to redirect the users browser is entirely depends on the Auth Server. Even it the client id and client secret are stolen and some malicious client app is pretending to be TinyBell's web app, if the Auth server already has a redirect url configured for a given client id during the TinyBell's OAuth App registration with Facebook, the OAuth server only tries to redirect the users browser to the correct web app url (But what if the browser is already compromised? Then throw that machine away 😂).


So far, whatever I just explained is called a Front channel request.

It's front channel because, other than the web app handing over the publicly known client id to the users browser to initiate the Auth call, the actual Auth code call is not tunneled through the Web app server. So, the web app is not directly involved in the Authorization code flow. The browser makes the Auth code to the Auth server outside the control of the web app to be precise. That's why this is called Front channel request. So, you can think of this process such as it's the Browser which is making an Auth code call first, get the code and give it to the web app to make the next calls. So, the Initiation of the OAuth flow starts with your browser. If the web app itself is able to make the Auth code calls, then wants the point of having the User approval? It doesn't make sense.

You might also be wondering how the web app is able to identify the user later once the users browser comes back to it with an Auth code? Does the client id help identify the user? No! The answer to that is session cookies the Web app also injecting onto your browser to later identify your session.


Let's move on

The Auth code which is now in the hands of the web app is short-lived, typically gets invalidated in matter of minutes. The Auth code is redirected to the web app url. Now what I am about to explain next is called the Back channel request. The Web app without any delay and any user intervention send a POST request to the Auth server using the original Authorization url requesting for an Access token in exchange of the Auth code, but the query parameters it sends now will differ. To avoid confusion of this url with the original Authorization url, some applications define this as "Access token url" or "Access url". But this url still belongs to the same Authorization server. To observe this in real life, the application POSTMAN defines two urls while using Auth code grant type, Auth url and Access Token url. And the Redirect url is also referred to as the Callback url.

Now, when the POST request is made to the Access url, we pass certain query parameters too. Those are

  1. grant_type=authorization_code, Indicating that the web app is requesting for an access token using the Auth code the Auth server has previously provided.
  2. redirect_uri, the same web app listening callback url we used to fetch the Auth code. This is used so that the Access token is sent by the Auth server as a query parameter when it callback.
  3. code=your_auth_code, this will be the Auth code
  4. client_id, the same application client id we used in the Auth code fetch procedure
  5. client_secret - Now here is the thing with client secret. The client secret is just a sequence of random characters just like the client id, but why do we need this again? During the login page the user is already authenticated with the Auth server. Secondly , the session cookies are stored in the browser. Thirdly, we passed down a state parameter to prevent CSRF attacks. And finally we sent a client id to identity the web app with the Auth server, well then what the heck is this client secret requited for?

    Well, this one is to avoid MITM (Man in the Middle) attacks. To avoid the secret man sitting in between your browser and the web app. While you were doing the Auth code process, an attacker could intercept your Auth code, and make a access token request pretending to be you. One might argue that this must be a secure channel already because the browser and the urls must be using TLS and the user is safe. But that's not the point.

    Even if the attacker receives the Auth code and the client id, he never had the client secret in the first place unless the connection between the Web App and the Auth server is compromised. Nowhere in till the Auth code fetch from the browser, the client secret is never revealed; even to the user. The client secret is only for the Web app's to use.

The Auth server once it receives the request checks the code, validates it string content and TTL, checks to see if the client id and secret matches and sees the redirect url again and sends back the Access token, TTL of the token (indicated as expires_in), scope for which your requested the token, token type dictating how to use the token (for example: to use the access token as a bearer token), and a refresh token which helps as a secondary access token used to fetch an valid access token in case previous access token expires. Now the Access token generation flow is complete.

The final step will be that the web app will either use the access token itself and hit the resource Server using the resource server url automatically, or it gives you "The user" the control to make one final request to access user photos. The web app never shows the access token to the user. Also, the OAuth 2.0 is not specifically used to get permissions to access user photos, but it is used to create user accounts based on the info present in the Resource Server about the users.

The resources server, gets the access token and would not be able to tell who the token actually belong to. Basically, It cannot identify the User or the Web app. It only knows who made the request, in this case the web app. The resource server then makes it own API call to the Auth server and asks it if the token is valid and whether it gave the token or not. If the Auth server vouches that the token is indeed a valid one, then the resource responds back with whatever the resource the web-app requested for based on uri or query parameters or POST body.

This process of using the Auth code first to get to the access token helps to prevent an attacker from stealing the Access token who had already intercepted the connection between the User's browser and the web app.

That's the end of Auth code grant type explanation.



The only difference between the Auth code grant type and the implicit grant type is that in the implicit there is no Auth code request, and the Client app directly requests for access token by passing the client id alone and there is no client secret from the very beginning call. So, a lot of back and forth calls between the client app and the Auth server is reduced, but this method is also used when the client absolutely trusts the user-agent which is requesting for the access token. The client has no ability to store the client secret with itself and it doesn't need to because everything is done in the presence of the resource owner. If you are the resource owner and the user that makes sense. But if you are just a user but not the resource owner, implicit grant types will not be considered.

That means the implicit grants are mostly not used when the client is not server sided, but client sided using Javascript and the client trust the user. So, the implicit grant is typically not observed on web apps which uses a browser, but mostly on native apps, because browser are vulnerable. Once again this means that access is allowed to the users if the client app wants to, and the user makes the access token call. The user and the user-agent can see the access token. If the user decides to share the token to anyone else and then that someone can access the user resources. As long as the machine or client native app which the user is using to make the request is secure this is fine. This is also fine if the.resources the user is sharing is their own data. But if the user is sharing the credentials of a business or their customers to someone else, or if the user gets hacked, well that's bad for the business.

Basically, the resource server trust the user, the user agent and the client believing that they know what they are doing, and approves access to the resources implicitly with no Auth code authentication.


The Client Credentials Grant Type

This is a grant which is used when the client wants to access it own resources but not the users. Since the client already resides in a secure server or a trusted device, it can directly pass the client id and client secret to fetch the access token from the Auth server and see no reason to exchange auth code for a token. There are no additional steps like using redirect url, Authorization url. Only use the Access token url by passing the client credentials. If you understand this much then the next grant type is much easy to understand.


The Password Credentials Grant Type

We are again working in the domain of trusted device much similar to client credentials grant type. The difference is in the previous grant type, the any person (user) who has access to the trusted device can exchange the client id and secret for an access token, but what if we have to restrict user access on some level. That's when we employ this grant. Each user gets their own username and password, and they have to pass them while also sending the client id and secret. The username and password hence authenticates the user, and the client id and secret authenticates the client. This also means the username and password must be registered with the Auth server. The password grant type is legacy.


The other grant types we specified in the very beginning are very similar to these. JWT just takes an extra step fetching a JWT token from an IDP or Issuer before making the Access token call. But thats the full picture of OAuth 2.0. Phew... That was a lot of work.


If you liked this article, please share it with your friends and colleagues and do write an email to me using the mailing address provided in the footer. You can also contribute any articles of your liking on this site if interested. Have a good day.