Serverless in the Google Cloud with Firebase & Cloud Functions
Google Cloud Platform’s best kept secret is Firebase. Firebase is Google’s “Mobile platform that helps you quickly develop high-quality apps and grow your business.” In short, it provides a lot of awesome development services like Authentication, Hosting, Real-time Database, and more. In fact, it even takes Google Cloud Functions and adds new triggers, so that you can kick off functions from events that seemed unavailable otherwise!
If you look at GCP’s Products & Services list, or even if sign up for a GCP account and start navigating the console, you will see scarce if any reference to Firebase directly. On the products page, for example, if you search the page for “Firebase”, there is a small link in a bottom footer to go to (next to Google+ links and Chrome Dev links) and that’s it. In the GCP Console, there is no direct link from the navigation area.
Your first thought(s) based on that are probably either “Firebase must not be very important” or “I guess GCP doesn’t have those services.” Fortunately, neither are true! Combining the power Firebase & GCP equals a stellar serverless platform.
My Journey to Firebase
My dive into Firebase came when I decided to build a new personal project on GCP to immerse myself deeper in Google Cloud Functions. I have done a fair bit with Lambda, but didn’t have the depth in Cloud Functions quite yet, so it seemed like an opportune time to remedy that.
Cloud Functions is still technically in BETA and has some areas for improvement at the time of writing this post:
- Only available in us-central1
- Only supports Node.JS
- Limited triggers: Pub/Sub, Storage, HTTP/S, and Firebase; (E.g. doing a time-based trigger requires some clever workarounds)
Like with most GCP services, Google does a good job of providing tutorials through sample use cases: https://cloud.google.com/functions/docs/tutorials/. The first thing I needed to figure out was authentication of the HTTP/S trigger for my serverless app. In the AWS world, I would front my function with API Gateway and integrate a Cognito Authorizer there, but that isn’t exactly how it works in GCP.
There is actually an article on “Authentication in HTTP Cloud Functions”, but it uses a pretty convoluted (in my opinion) method of checking for storage.bucket.get access:
Enter Firebase Authentication
I searched for other solutions for Cloud Functions authentication as I wanted something similar to the AWS Lambda + API Gateway + Cognito approach. I ended up at: GitHub / firebase / functions-samples / Authorized HTTPS Endpoint. The example leverages Firebase Authentication as ExpressJS middleware inside the Google Cloud Function to provide authentication. It’s an easy method to add Authentication, although I am conflicted architecturally on having my authentication directly inside my Function versus at the API Gateway.
The above diagram shows how the authentication works at a high-level. The user accesses the static site hosted on Firebase Hosting, which provides client-side authentication through Firebase Authentication. That Firebase Authentication token is then passed to the Google Cloud Function and verified; if verified, the function runs. The demo code really only verifies that the user has a Google Account and nothing more (more granular access is left as an exercise to the reader).
Deploying a Serverless App with Firebase
Firebase is great for more than just adding the Authentication component to Cloud Functions. It’s actually a great serverless platform that provides a whole collection of development services: Hosting, Functions, Database, and more. (Site Note: Many of Firebase’s services are things one might not think exist within GCP with only a casual glance, which is why I hope Google integrates Firebase & GCP from a UI/Marketing perspective better in the future).
Deploying an application with Firebase can be as simple as:
- Creating the Firebase Project
- Installing firebase-tools on your system through npm:
npm install -g firebase-tools
- Logging in at the CLI with
- Configuring what Firebase project to use with
firebase use --add
- Deploying with
The firebase tools also come with local emulators, including for Hosting & Functions, so you can test as simply as:
firebase server --only hosting,functions then browsing to localhost your local dev machine!
Firebase Projects tie to GCP Projects, and Cloud Functions within Firebase deploy within the GCP Console as relatively normal Functions. I wish the UI was a bit better integrated, but the services on the backend work well together regardless.
There are a lot of tools within Firebase beyond hosting and functions, so I encourage everyone to check them all out. I suspect most folks will be very impressed.
Breaking Down & Extending the Sample Code
The sample code provided by Firebase for authentication is great, but I wanted to fork it to provide some additional capabilities as well as put it into my coding/UI/template style.
Overall, I kept the function mostly the same, but added a few things for demo purposes:
- I wanted to be able to call the function directly (e.g. through Postman) with a token, so I added the
/tokenroute which displays the token that can be placed in the Authorization header inside Postman for example.
- Added a
/worldroute to show it’s easy to just keep adding routes here, if desired.
This is the area I changed the most.
- I prefer to use Bootstrap for my front-end components versus the included usage of Material Design Lite, so
index.htmlwas modified to swap these.
- I added some basic look and feel components like a navbar.
- The original code included showing usage of direct Authorization and using the
__sessioncookie. I swapped it to simply use the Authorization method. (Site note: The
__sessioncookie can be set if you want to be able to call the Cloud Function directly from another tab for example, but isn’t really required for persistence within the app.)
- Added a card that shows the User’s details (e.g. Display Name, Email, etc.) after logging in.
- Included some logic for creating the API URL for portability (e.g. more cleanly define the URL for all cases).
The outcome was the creation of a simple template I can use to create serverless applications on Google Cloud Platform & Firebase: https://github.com/eeg3/gcp-firebase-serverless-demo. I hope this is useful to someone that wants a simple starter demo, and hope it encourages folks to try out the great combination of Firebase & GCP.