The Token to understand OAuth

Photo by Andrea Piacquadio (Pexels)

Is OAuth2 driving you nuts? No reliable resource for a beginner. Well, you’ve come to the right place!

In this piece of article, I shall explain OAuth to you in such a way that you would never need to go to any other article on OAuth.

OAuth! In my early developer days, this term used to electrify me for some reasons. If we think of securing something on the internet, the one (and only) thing that comes to our mind would be Passwords and its cousins like API Key, PIN etc. But one-size-fits-all is a terrible thing in the vastly heterogenous world of the internet and computers especially while protecting your resources from third party or hackers. This is there the wonderful “OAuth” (or the modern OAuth 2.0) comes into play.

IETF, the standard setting body has published an RFC where the abstract of OAuth is defined:-

“The OAuth 2.0 authorization framework enables a third-party
application to obtain limited access to an HTTP service, either on
behalf of a resource owner by orchestrating an approval interaction
between the resource owner and the HTTP service, or by allowing the
third-party application to obtain access on its own behalf.”

Oops, that went over your head. The same with me. Until I used its practical use case, Amazon Cognito. However I will simplify the above definition in the coming lines which will enable you to fully understand it and prompt a few questions out of you.

On breaking the abstract, we get that:-

  1. OAuth2 (aka OAuth 2.0) is an Authorization (definition: document giving official permission) framework which enables a third party (definition: a person or group besides the two primarily involved in a situation) to obtain limited access to an HTTP service.
  2. Either on behalf of a resource owner OR
  3. By orchestrating an approval interaction between the resource owner and the HTTP service OR
  4. By allowing the third-party application to obtain access on its own behalf.

Points 2, 3, 4 may give you a hint that the RFC specification leaves many decisions up to the programmer to take decisions based on tradeoffs and use-cases.

The entities participating in this protocol assume one of the roles mentioned below:-

  1. Resource Owner: An entity capable of granting access to a protected resource.
  2. Resource Server: The server hosting the protected resources
  3. Client: The application that is attempting to get access to the protected resource with its owner’s authorizartion. Note that the term ‘Client’ is not referring to the client in a ‘client-server’ model.
  4. Authorization Server: Server that either allows are denies request to access the protected resource

Imagine you build an application which requires the user’s data (contacts, location etc.) which will be stored in the user’s email account. The straightforward way of doing this is asking for the user’s account ID and password and collecting the information. This is exactly what facebook did in its early years to connect with other apps :)

But this is 2021, and Oauth2 does this in a much more sophisticated and robust manner without needing your password.

So if your application needs access to the data, you need to register an “app” with the vendor where the user has stored their data. One important parameter to provide is the “Redirect URI” of your appliaction while registering your app.

Note that your application is different from the “app” that you would register. An app is simply you registering your application with the service for it to work with OAuth2.

While registering your application, you need to provide some details. the most important and must required detail is the Callback or Redirect URI.

After registering your app, you will receive a client ID and optionally a client secret. The client ID will be an identifier to your application that uses the service on your behalf. The client secret is must not be public (as the name implies). When the application that uses OAuth2 to communicate with the service is a user facing app (JS Frontends, Mobile Applications), the client secret shouldn’t be utilized as the code is available to the user’s disposal.

The below figure is taken from the RFC document. It describes the abstract protocol flow and will be aiding my explanation.

Abstract Protocol Flow

The above figure must be registered in your mind to remember OAuth and to not to forget it sooner.

In a nutshell, we ask “permission” from the Resource Owner and Authorization Server to access data from the Resource Server. Here Resource Owner authorizes the client and Authrization Server provides a “token” which contains information about the scope (Eg. Read Write Permissions on various data) and expiry of the token. The token isn’t encrypted (but is encoded), but it signed to ensure the validation and security aspects of the communication.

The token provided is a JWT (JSON Web Token)

Definition: JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.

Read more: https://tools.ietf.org/html/rfc7519

The first thing that you notice in the image is that Client (You application) requests for authorization from the resource owner (A). Client ID and optionally client secret is used to obtain authorization grant.

OAuth provides different types of Authorization Grants based on the use-case. They are: authorization code, implicit, resource owner password
credentials, and client credentials

We would be discussing the authorization code grant for the sake of understanding.

In Step (A), a request is made to the resouce owner which looks like the following:

https://some-api.com/oauth2/authorize/?client_id={clientID}&response_type=code&redirect_uri={redirectUri}

Optionally client_secret is going to be sent in the query parameters. In some applications, the redirect URI is going to be preregistered and hence wouldn’t be required in the above call.

Note: A nonce or a state value is going to be used to ensure that the communication wasn’t subjected to a MITM attack.

After the above call is made, the user has to authorize the application to use their data on their behalf. This is the step where you “Allow” or “Deny” permissions (You would have encoutered this dialog a lot of times while browsing through the web)

If the user authorizes the application, the following redirection would be made in the below given format

https://my-redirect-uri.com?code={authCode}

This completes the request (B) from the image. The server is also going to send the nonce value that we sent. This is to make sure that that our redirection URL wasn’t tricked by some random server posing as the resource server that we intended to communicate to.

We now have an authCode a.k.a. Authorization Code which is an intermediary to obtain the Access Token.

Note: The flow that I am talking about (where authCode is returned) is Authorization Code grant. In case of an Implicit grant, instead of issuing the client an authorization code, the client is issued an access token directly (as the result of the resource owner authorization). The grant type is implicit, as no intermediate credentials (such as an authorization code) are issued (and later used to obtain an access token).

The authorization code is obtained by using an authorization server
as an intermediary between the client and resource owner. Instead of requesting authorization directly from the resource owner, the client
directs the resource owner to an authorization server which in turn directs the resource owner back to the client with the authorization code.

Since, the resource owner only authenticates with the authorization server, the resource owner’s credentials are never shared with the client.

The authorization code provides a few important security benefits, such as the ability to authenticate the client, as well as the transmission of the access token directly to the client without passing it through the resource owner’s user-agent and potentially exposing it to others, including the resource owner.

After we obtain the authCode, we send the authCode to the resource server (Request ( C)) and in return, we obtain the Access Token (D).

The end result of all the authorization grant types is obtaining an access token.

This Access Token is a JWT Token that can be used to access the protected resource (the users’ personal data) and the token defines the scope for doing the same. This is defined by Steps (E) and (F).

Access Token have an expiry time. To “reclaim” the access tokens to use it after it expires, we make use of “Refresh Tokens” whichcare returned in Step (D) along with the access token.

The client can trade the refresh token with the authoriztion server for fresh access and refresh tokens obtained in step (D). Note that for there will be a seperate API endpoint in the Authorization Server for doing the same.

We can use the Access Token to obtain access to protected resource by doing the following

POST http://resource-server.com/protected-resource with “Authorization: Bearer <AccessToken>” passed in the header.

If you want a more elaborate diagram on how OAuth works with Authorization Code Grant Flow, then here you go.

Credits: www.websequencediagrams.com

OAuth2 is a sophisticated and a wholesome way to exchange information on the web. OAuth and its sister protocols like OIDC has made the lives of an average internet user easier and secure. Hence these are extensively used in the field of web development and every web developer must know atleast the surface level information about OAuth2.

Hope you enjoyed the article! Hit those claps if you liked and please provide your valuble feedbacks. Thank You!

Bonus: How Refresh Tokens work?

Refreshing an Expired Access Token

(A) The client requests an access token by authenticating with the authorization server and presenting an authorization grant.

(B) The authorization server authenticates the client and validates the authorization grant, and if valid, issues an access token
and a refresh token.

(C ) The client makes a protected resource request to the resource
server by presenting the access token.

(D) The resource server validates the access token, and if valid,
serves the request.

(E) Steps (C ) and (D) repeat until the access token expires. If the
client knows the access token expired, it skips to step (G);
otherwise, it makes another protected resource request.

(F) Since the access token is invalid, the resource server returns
an invalid token error.

(G) The client requests a new access token by authenticating with
the authorization server and presenting the refresh token. The
client authentication requirements are based on the client type
and on the authorization server policies.

(H) The authorization server authenticates the client and validates
the refresh token, and if valid, issues a new access token (and,
optionally, a new refresh token).

Note: The Bonus section is taken from the RFC document. Do take a look at it here

Software Engineer