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.
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.
The user submits their email and password to the User Pool, which then authenticates the user and sends back a token.
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.
Here is an example of a Code Token returned in a URL after using the hosted UI.
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.
Here is an example of an implicit grant JWT Token returned in the url.
Format sample from documentation:
actual returned token:
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.
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.
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?
Review the following links before continuing.
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:
- extract code from URL
- put code into
- handle response
Let’s walk through all of that now.