Verify and Decode Cognito JWT Tokens
Intro
Previously we have covered the process of retrieving JWT Tokens from the Cognito Token Endpoint.
📘 ncoughlin: AWS Cognito Notes
Next we need to decode the tokens to get the information inside, and then verify the signature of the tokens to ensure they are legitimate. There are libraries that exist just for this purpose, and because we are using Node as our environment we need to find a node library.
Resources
AWS Docs: Verifying a JSON Web Token
Github:auth0/node-jsonwebtoken
Understanding the JWK
Before we go forward with a complete example let's quickly make sure that we understand the theory behind verifying the signature of a JWT. As we know the JWT contains three sections.
- Header
- Body
- Signature
The signature is what we check to make sure that the token actually came from Cognito and not a malicious 3rd party conducting a man in the middle attack (MIM). We verify the signature by using a public encryption key that Cognito creates and provides for us (this is described in more detail in the docs linked above). One of the tricky things to understand about this however is that the public key is publicly available. Anyone with our user pool id could retrieve this key. So if anyone can retrieve our public key how do we know that a MIM attack isn't just using that key to create a fake signature on the JWT?
This is answered with a fundamental understanding of the difference between private and public keys.
- Public Keys: Can decode a signature
- Private Keys: Can decode and encode a signature
These keys are created mathematically in such a way that only the private key can encode something, while the public key can decode it. Therefore we can use the public key to verify that signature was created with the private, which only Cognito has access to.
So in short, there is no way for a MIM to fake a signature. A MIM could intercept and decode our signature, or even steal the credentials and log in to our API, but they could not fake a signature from Cognito.
The ability to possibly intercept our tokens is why 0Auth2 puts a time limit on access tokens, and why using secure connections is so important.
Decode the JWT Token
The node-jsonwebtoken library linked above has the ability to decode and verify the JWT token all in one method. That method takes the following format.
jwt.verify(token, secretOrPublicKey, [options, callback])
At this point in the process we have the token but we have not yet retrieved our Public Key.