AWS Cognito Notes

Intro

I’m convinced at this point that AWS has some sort of internal rule that their documentation should be intentionally vague and never include any actual code samples. The goal here is to provide a more clear overview of how Cognito actually works, and provide actual detailed code examples for receiving and exchanging tokens.

We will not be using Amplify here.

Hosted UI Flow

When the user is signing in you can either have them use a custom form that is linked to Cognito on the back end using the Cognito SDK, or you can use the hosted UI, where the registration, login, password reset forms are all handled for you. We will look at the process of using the hosted UI here.

there is actually a third option where you can use Amplify prebuilt components but we aren’t using Amplify as it limits flexibility

Let us start with the user signing in using the hosted UI.

cognito hosted ui

user pool authentication diagram

The user submits their email and password to the User Pool, which then authenticates the user and sends back a token.

Response Token from User Pool

πŸ“˜ AWS Cognito: Handling User Pool Tokens

The User Pool will return to us a token which will be in one of two possible formats

  • token Code
  • Implicit Grant token

The response type is chosen by you in your User Pool settings. You can also enable both methods and then specify which one you want to use by changing the URL of the hosted UI.

The token will be inserted into the URL as a query parameter when you are redirected after a successful user authentication with the User Pool. See just below for examples.

Code Token

Here is an example of a Code Token returned in a URL after using the hosted UI.

https://app.widget.io/?code=0162d843-cd07-4e34-9594-d4bdc91bd270

This code must be exchanged with Cognito via the SDK to receive further information about the user.

The Code Grant method is the preferred method as it is much more secure. It does not pass any JWT Tokens directly to the client, potentially exposing them.

Implicit Grant JWT Token

Here is an example of an implicit grant JWT Token returned in the url.

Format sample from documentation:

https://www.example.com/#id_token=123456789tokens123456789&expires_in=3600&token_type=Bearer

actual returned token:

https://app.widget.io/#id_token=eyJraWQiOiJ0T2ljeHUxZGhGVkt5ZHl0K2ZqbVowSXF1NHRJa1ZUWEJ5MWRSRnRPVnU4PSIsImFsZyI6IlJTMjU2In0.eyJhdF9oYXNoIjoiSVhmWUNTYjhVekRjN0U0X1gzTTlGZyIsInN1YiI6IjY0ZWE4OWFiLTU3NWYtNGJhNC1iMGE2LTNiMGJmOTAyNWQxZCIsImF1ZCI6IjFxNW84OGI2ZW5rdjMwdTZnYnZhdWV1bWI4IiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImV2ZW50X2lkIjoiN2ExMGQ4YmQtNWI2Zi00OGM0LTk1MTUtYjVkOWE3N2IwNjA3IiwidG9rZW5fdXNlIjoiaWQiLCJhdXRoX3RpbWUiOjE2MTc5ODI2MzYsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbVwvdXMtZWFzdC0xX1cxWE5MTkhOWCIsImNvZ25pdG86dXNlcm5hbWUiOiJuY291Z2hsaW4iLCJleHAiOjE2MTc5ODYyMzYsImlhdCI6MTYxNzk4MjYzNiwiZW1haWwiOiJjb3VnaGxpbi5uaWNob2xhc0BnbWFpbC5jb20ifQ.GUvRcyol8zpOEni8VqUjJLNfPchqfNw0xKUcVAEicwIUpHGqMNQYGddY8gNFp1web4fW8LCwOQOLkHpFeruhkHV3z8ek5vx0cTctAsPgVspUG0faiAn-5zxNbI-MfiLppKFCkU3n2EZhntEWAzBybOQQRbrTV7rZ_jygkIoLtI4Xr-RwaTanXd9tsHJ0pTqvtTXOWLsnXwBF0U5z-DK4XlQeRvnhDAILvq63t52Ne2RFhojTIPu82GsATpV4qHhiB120BcyF85TJbturJ7qlF7QD3SRlzhIF0A1DU5O5EseELIWc9GH_bIG2DVxKImy_Bx3ucsQ601zAJWODEVm3RA&access_token=eyJraWQiOiJyeit0d0t3YThEUURZaEYzYmVTYTR2VUhsMktGTFRRcnJ6VklcL3Bxd3M4ST0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI2NGVhODlhYi01NzVmLTRiYTQtYjBhNi0zYjBiZjkwMjVkMWQiLCJldmVudF9pZCI6IjdhMTBkOGJkLTViNmYtNDhjNC05NTE1LWI1ZDlhNzdiMDYwNyIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoib3BlbmlkIGVtYWlsIiwiYXV0aF90aW1lIjoxNjE3OTgyNjM2LCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZHAudXMtZWFzdC0xLmFtYXpvbmF3cy5jb21cL3VzLWVhc3QtMV9XMVhOTE5ITlgiLCJleHAiOjE2MTc5ODYyMzYsImlhdCI6MTYxNzk4MjYzNiwidmVyc2lvbiI6MiwianRpIjoiYTkyZmNhODgtZjMyNi00YTFjLWFhNGQtYWFhYTA4MzdjMjNiIiwiY2xpZW50X2lkIjoiMXE1bzg4YjZlbmt2MzB1NmdidmF1ZXVtYjgiLCJ1c2VybmFtZSI6Im5jb3VnaGxpbiJ9.Oe8QvsLg1YQ0TLdKCcCWL-fXNXUXUcyh1UYCLvtgOlj7tGUF-4xBli3npcRxlra9WQN8qGDp4BK3ao8DIyVnm3U0ar2GVbyobUOiVWtzb0YUFmjFgUvw_Da3M6F7ok0whxVu58HXM1LhNY_HpKU6WRO37V63ac891KQieFqzkp1BkqdEvZPvhET6ZR3gBplp0L-MwUZSulQk-5g9rXfIpXQz4LggwIhKrAFfe1JeUAtKd62Uk2EMUI8peI_kEZMDImNHzpUf7Et3gfFZFDAsci0D0qjgmLOvte4K6tzh4tDWL18hSkJzbIJ6T5iNRTorzvn1JUXEuZEYkHQATMytXw&expires_in=3600&token_type=Bearer

This is a full JWT token which contains a header, payload and signature. Specifically this is a Cognito ID Token, as opposed to an Access Token or Refresh Token. It is encoded with the RS256 algorithm, however it can be easily decoded using jwt.io to see what information is contained inside.

jwt.io decoding

So as we can see, this information is not secure if it is intercepted.

If you are going to use the implicit grant method and get the full token back immediately, you must verify the signature of the token to ensure that it was actually issued from Cognito. This is a potential avenue of attack otherwise.

Therefore let us move forward taking the best practice approach, and work only with the code grant method.

Exchanging Code Token

At this point we have received a Code Token from the User Pool. This code, as shown above, is completely useless to us until we exchange it for useful information. But the user has been authenticated and a timed session has been started for this user. Cognito is ready for us to send this code back with a further request for more information.

Note that in a lot of the documentation this Code is referred to as a Token. This is not to be confused with a full JWT Token, which is a full encrypted JSON object. However in an attempt to simplify their documentation AWS will often not specify which of the two methods they are referring to, and will refer to both as simply Token or JWT Token.

So how do we exchange this code for useful information like getting the users profile information?

There are several tools available for this. If you are using Amplify you would use the commands built into the Amplify SDK. We are doing this without Amplify. That means that we will be using the AWS Javascript SDK methods to retrieve our user profile.

Review the following links before continuing.

πŸ“˜ AWS Cognito API: GetUser

πŸ“˜ Javascript SDK v3: GetUser

exchanging code token diagram

So we can see that we need to use the Code Token that we got as a parameter in our request, and then use the getUser method to retrieve our user profile information. So we need to follow these steps:

  • scaffold getUser request
  • extract code from URL
  • put code into getUser request parameters
  • send getUser request
  • handle response

Let’s walk through all of that now.