If you’re reading this, I imagine you’re in a similar boat as I am. For some reason, we have our toes dipped in multiple cloud providers, rather than going with the seamless authorization that AWS Cognito provides with AWS, we’re using Firebase. Until now, our only choices has been as follows:
- Create a custom authorizer, which is effectively another lambda function that’s invoked before the target lambda is invoked, which then passes the authorization metadata to the target lambda. Here’s an example of what that lambda might look like.
- Just do the JWT verification in the target lambda itself.
Neither of these solutions is ideal. The first, introduces another chance for a cold start, and the syntax is a bit funky for anyone unfamiliar with AWS policies (…honestly even for those familiar with it.). The second, is a bit brittle, not only are you introducing a dependency on the firebase admin for the particular language into each and every lambda that’s a target of your API Gateway, but this also requires that you keep all of these separate functions secure in the functions themselves.
There has to be a better way — Everyone who’s ever done this…or just me
With the recent announcement of API Gateway HTTP APIs, this issue is finally put to rest.
Let’s get right to it, let’s first do this in the console directly, to really get a feel for this, and then I’d like to share a few resources to automate this.
If you already have a lambda setup, be sure to create one now — the default function will work for now.
Alright, from the AWS console, navigate the the API Gateway page. From here, we are going to create a new API, of type HTTP.
Once you’ve navigated to the screen to create the new HTTP API, click Add Integration, and fill the values in for an integration type of Lambda, in your desired region, and select the lambda from the options (once you focus into the input field) you should see a screen like below.
On the following screens, set them up as you’d like, or just proceed with the defaults.
Now that we have our API, it’s time to add the authorizer — to get there, navigate to Authorization from the detail page of your newly created API. (You might have to click the menu icon in the top left to expand the left navigation).
From this screen, select the Manage Authorizers tab, and click “Create”
Now, we just need to fill out the values in the form. For Firebase, this is very standardized, for the initial name, the value is arbitrary, so use whatever you’d like. See the image below for guidance on the values. The identity source is also specific to your implementation, if you pass in the authorization token as anything other than “Authorization”, be sure to adjust the “$request.header.Authorization” to reflect that. Lastly, simply update the issuer, and audience replacing “replace_me” with your firebase project name (the name you see in the top left of the console).
Now that the authorizer has been created successfully, let’s attach it to the endpoint(s) we created before.
At this point, your endpoint will validate the JWT token passed in by Firebase before it hits your lambda! 🎊🎊🎊
If you’d like to take your lambda further, here’s a sample event you’ll get on your lambda once you’ve had a successful invocation.
Now, to wrap up, this definitely isn’t an ideal way to set this up, especially if you have to replicate this across many environments, and regions.
At the time of this article, I’d recommend serverless for this. I’m also a huge fan of terraform, but at this time there is no support. Also, for anyone who’s worked with the resources for API Gateway with cloud formation, it’s a bit cumbersome (serverless abstracts this).
Alright, the essential element here is a serverless.yml, this will look something like the screenshot below.
Be sure to go through the getting started with serverless if you’d like to try this out. It’s a very quick install, but you’ll also need to link your AWS account.
I won’t dig too deep into the details, they do a great job of explaining the details of the http apis in the serverless documentation, furthermore, they have excellent documentation to get you up to speed quickly.
Once you have your configuration file setup, it’s as simple as running
serverless deploy --stage $DESIRED_STAGE done!
With the simplicity of serverless in place, it’s very easy to automate your deployment process with a pipeline. Please leave a comment if that’s something you’d like to learn about, or simply see my perspective on.
If you’ve made it this far, I really hope this has been helpful, and I thank you for taking the time to read!