Securing API calls
Now that we have a fully functional API that allows you to register and login, the next thing is to put our authentication to good use in the shape of securing API calls.
There’s a couple of ways we can use Cognito as a way to authenticate callers into an API. A very popular way is to use Cognito as an Authorizer for REST APIs. Because this is fairly well documented I will focus on a slightly more complicated use case which is when you want to manually validate a JWT token provided by Cognito. This is a slightly more complicated task but it gives us some granularity on how we handle the errors a bit better.
As with all the previous posts, the source for the project I’ve been working on it’s on my personal Github.
What will our demo API do?
Well we need a demo to illustrate the point, our demo API will return a header. It sounds simple right? A topic I’ve always enjoyed is Microfrontend architectures as it’s a very good way to scale applications to multiple product teams working on separate user spaces so I’ll use a bit of that now.
Imagine as a team you’re responsible for crafting the Header of your application. There’s 2 ( could be more but let’s keep it simple ) states your header will have, one of them is logged in and other is when you have an anonymous request — ie, somebody who’s not logged in.
For the case where a user is not logged, we want to see something like this:
And for the case of a user that’s logged in
So that’s a fairly simple problem to work with.
The behaviour we want to achieve is fairly simple:
- Every user with a valid authorised JWT token will be given a logged in header.
- Every user without specifying a token (or with an incorrect one) will be given the anonymous header.
This is where this can be quite handy, because we want to have such a specific custom logic on our flow, doing the authentication ourselves will give us a lot of granularity.
Decoding a JWT token
There is a lot to be said on how to decode a JWT token as you need to parse the token from its base64 form, then you need to retrieve your Cognito public keys to then be able to verify your parsed token against your public keys and be able to access the information for the user and their claims.
Admittedly that’s a lot, I will not go into the whole process but if you really want to have a look you can check out on the project I created called lambda utils, more exactly on the Security side of it.
If we use this library, then the process is a bit simpler and the function to check a given token becomes this simple:
All we need is to validate the credentials and make sure they have the right token. If an invalid (or expired) token is provided this will throw an exception and we’ll just get a
Once we have this function fully sorted, our lambda can look as simple as this:
Important to note how in case of error validating the token or any error we just return an anonymous response. Meaning the users will (almost always) see something even when the validation fails.
Because we have the control over the full process, it’s perfect for creating metrics of how many times your API has been called with expired tokens or with fully invalid tokens which can be quite handy for monitoring the availability of your application as a whole.
This was a much shorter post compared to others as we’ve been building on what we’ve done and using some helpers to save a lot of time. If you have the time, dig into the source of validation inside the library quoted as this can bring you some good insights on how it all works.