\Visual explanation of OAuth 2.0 Authorization Code Flow with Amazon Cognito

Alexander Osipov
7 min readNov 17, 2022

--

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. — RFC-6749

Let's say you have a mobile or web application and want to allow your users to see events in Google Calendar inside your app. How can your app securely get access to users' calendars?

This article explains how to get an access token using OAuth 2.0 Authorization Code Flow. With practical examples and visual support, we'll cover the core concepts of the protocol, and I will show you how to implement it in a sample application.

You can find a complete example of implementing this flow in my GitHub repository.

What makes Auth Code Flow worthwhile?

While learning how Auth Code Flow works, I identified the following concepts that make this flow so useful:

  • The end-users (the resource owner) credentials are never shared with the app (the client). It becomes possible by using an authorization server as an intermediary between the client and the resource owner. The client only ever receives an authorization code, which it can then exchange for an access token.
  • In OAuth, the client (the app) requests access to resources controlled by the resource owner (the user) and hosted by the resource server (Google Calendar) and is issued a different set of credentials (an access token) than those of the resource owner (username and password).
  • The concept of Redirect URL allows the client to receive an authorization code after the resource owner completes authentication and grants content.

Important concepts

Here are some important things that we need to know to understand the process fully:

  • Authorization Code — is a form of the authorization grant. It tells that the resource owner (a user) grants the access request to the client (an app). The authorization code is issued by the authorization server and delivered to the client via Redirect URL. The client uses an authorization code to request the access token.
  • Redirection Endpoint (Redirect URL) — Auth Code Flow specification uses HTTP redirections extensively. After authenticating the resource owner and getting an authorization grant, the authorization server directs the resource owner's user-agent (browser) back to the client's Redirection Endpoint. It includes an authorization code in the response.

Auth Code Flow Step-by-Step

Using the official terminology, OAuth 2.0 is an authorization framework that enables clients to use resource servers on behalf of resource owners. And this is how it works.

Step 1. It starts when a user wants to access external data through your service. In OAuth terms, your app is the client, and I am the resource owner (I'm the owner of my own Google Calendar):

Step 2. Initially, your app (the client) does not have an access token for Google Calendar (the resource server):

Steps 3 and 4. So, to get one, it will initiate an authorization flow by redirecting my browser to the login page, where I need to sign in (authenticate myself) using my social profile or email and authorize (grant consent) your app to access my Google Calendar's data.

Your app also specifies the list of requested permissions it is needed (the scope), and a redirection URI, where the authorization code will be sent later.

Step 5. Once I signed in and provided consent, the authorization server authenticates me (the resource owner) and establishes whether I granted or denied the client's access request.

6. Assuming access is granted, the authorization server redirects my browser to your app using URI redirection. The redirection URI includes an authorization code and any local state provided by the client.

7. Your app requests an access token from the authorization server's token endpoint by including the authorization code received in the previous step. When making the request, your app authenticates with the authorization server. Your app also includes the redirection URI used to obtain the authorization code for verification.

8. The authorization server authenticates your app, validates the authorization code, and ensures that the redirection URI received matches the URI used to redirect your app in the previous step. If valid, the authorization server responds with an access token and, optionally, a refresh token.

9. Finally, the client requests the data from the resource server, including a new access token. The resource server returns data if the token is valid and has proper permissions.

Prerequisites

Setting up OAuth2 requires some preliminary work. Here is the list of prerequisites we would need to have to make Auth Code Flow work properly:

  1. First of all, we need to have a user pool created in Amazon Cognito and an app client registered like this:

2. We will be using Google to sign in users in our application, so we should link it to our Cognito user pool like the following:

3. Also, we need to configure attribute mapping between Cognito and Google so that we can access Google-provided attributes in Cognito tokens:

4. Finally, we link the Google Identity provider, configure the callback URL, and specify allowed OAuth flows and scopes:

Now we are ready for testing!

Implementing Auth Code Flow in a sample app

To better understand the concepts we've just discussed, let's implement them in practice.

Our app is a simple python script that will connect to Google Calendar API and retrieve the list of users' calendars. And it requires an access token to be able to access Google API.

To get an access token, we need to define a client_id, and client_secrets of our app registered in Cognito, a redirect_url, where Cognito will send an authorization code, as well as token and authorize endpoints from Cognito Hosted UI:

Most providers will request that you ask for access to a specific scope. In this example, we will ask Google for access to the user's calendar and profile.

User authorization works through redirection. So, first, we will create an authorization URL from the base URL given by the provider and the credentials previously obtained:

You will be prompted to open the authorization URL and sign in using your Google account. Once you have completed authentication, copy the entire redirect URL and paste it back to the console:

After obtaining an authorization code, we can get an access token:

There is one trick here. Remember, we have configured attribute mapping between the Google Identity provider and Cognito User Pool? So, Google's access token (which provides you access to Calendar API) has been added as an attribute inside the id_token issued by Cognito. So, to be able to access Google Calendar API, we need to extract that token first:

Finally, we can call our app, pass an access token to it and see all our calendars in the output:

Here is how it all looks in practice:

Conclusion

Confusing and may be hard to appreciate initially, this flow gives you a flexible way to access any OAuth-protected APIs.

With Cognito, you can include multiple identity providers and hide them behind a single interface. Also, you can use OAuth to get access to AWS resources and get temporary credentials via IAM.

I hope this article is useful and helps you better understand the protocol's internals.

Thanks,
Alex

--

--