How to test your secured GCP cloud functions
“TLDR: In this post, we are going to explain how you can test Firebase functions that only accepts authenticated Firebase users. We do this through our example code and the VS Code extension made by Huachao Mao”
Prerequisites
- VS Code, although you can use any tool that can make HTTP request
- If you are running VS Code, we recommend the extension made by Huachao Mao to structure your HTTP requests
- A running Firebase emulator: If you want to set one up without a hassle, check out our previous blog post Setting up Firebase Emulator and or pull our example code from GitHub
Instead of using the emulator you can also use your hosted production/development environment. You can do this by using the Firebase REST API and passing in your project API key
The Problem
You have created cloud functions that can only be called by an authenticated user. This security layer only allows your authenticated Firebase users to make certain function calls.
When working with the application, this is easy to test since you just log in and make a request with the logged-in user.
But when you want to test your functions without your application, you will bump into the issue of not having an easy login point or way to keep track of the user token without manually inserting it each time.
Have no fear, because the solution is near!🤓
The Solution 💪
To show you it can be done without copying auth tokens, we will use this extension within VS Code.
To follow along, use our example repository and make sure you have installed the VS Code extension or use the CURL calls provided by the Firebase documentation.
Note if you are going to use CURL you will have to copy your authtokens by hand
Before we reveal the solution, we are going to provide some background on the following topics:
- The Firebase project and the function under test
- How to use the Google Identity Platform REST API
- How to make it reusable using the VS Code extension.
- Combining all the knowledge 🚀
1: The Firebase project
For this blog post, we made an example repository that you can find here.
In this repository, we have a Firebase project that contains one function. This function is protected by the requirement of having a valid user token in its Authorization header.
When the user is not authenticated, it will receive a message that the user is not allowed to be here.
When the user is authenticated, you will get a nice, warm welcome message.
You can call this function by running the emulator and requesting it on the following URL.
http://localhost:5001/default/us-central1/helloWorld
If you want to set up your emulator, follow our previous blog post.
Make sure you run npm install && npm run build
in your functions
directory before starting the emulator. This will make sure your function and its dependencies will be compiled
2: The Google identity platform rest API
To be able to register/login into the Firebase environment, we need to make certain REST calls to what is called the Google identity platform (GIP). The Firebase suite uses GIP to manage user identities in the system. The REST API has many features, but for our use case we will focus on registering and logging in with the created user.
To achieve this, we need to use the following endpoints:
- registering: /v1/accounts:signUp
- logging in: /v1/accounts:signInWithPassword
To call these endpoints on your emulator, you need to add the IP and port of your auth emulator like so.
http://localhost:9099/identitytoolkit.googleapis.com
To run it against your online environment use
https://identitytoolkit.googleapis.com
So to call the register API on your emulator, you would use the following URL
http://localhost:9099/identitytoolkit.googleapis.com/v1/accounts:signUp
To use the online environment, you would use the following URL
http://identitytoolkit.googleapis.com/v1/accounts:signUp
3: VS Code REST Client Extension
To streamline these REST calls, we will write them down in a .http file and use variables for better reusability.
To create a variable in the .http file, you use the following syntax.
@authToken = value
To use this variable in your requests, for example in a header, you can do the following.
Authorization: Bearer {{authToken}}
This will inject your @variable value into the Authorization header.
The real power of these variables are that they can be filled by the response of a request. So to store your idToken that you receive from a login response, you can do the following.
@authToken = {{login.response.body.$.idToken}}
This will fill the @authToken variable with the idToken found in the login response body.
The next step is creating a request. You can do this by just writing your method type and URL of the endpoint in the .http file like so:
4: Combining G.I.P with VS Code
Now that your function is ready to be called, and you know the ins and outs of G.I.P and the neat VS Code extension, it is time to combine those 3 into a powerful tool.
We need to make a .http file that contains the ability to register/login, store the auth token and be able to call our cloud function.
To do this, we reuse the lessons from the previous chapter and design our file with the following content.
Make sure your gipURL and cloudFunction URL variables point to your emulator or online environment.
If you have installed the restClient correctly, you should see a “Send Request” button appear above your API calls. Like shown in the picture below.
If you click the “Send Request” it should register a new user into your backend when configured correctly.
Try clicking the request for your cloud function “the one at the bottom” and it should inform you that you are unauthenticated. To authenticate your self, click the “Send Request” at the login and then try again.
It should now show you a warm welcome message containing your test user email.
An example of the flow you can perform is shown below
🚀(register ➩ login ➩ cloud function) 🚀 ➩ 🌕
Now you can test all your functions that require an authenticated user, from the comfort of your editor.
Treat for our readers ⛄️
Do you also hate making time-consuming breakfasts? Well, we have a solution 💪 try out this recipe:
- Get a mug
- Make sure you have : 4 tablespoons of oats, 1x banana, handful of walnuts, 1 egg, 1 tablespoon of cocoa powder and 1 tablespoon of honey.
- Perform the following:
* Squash banana in mug
* Add egg and oats and stir until nicely combined
* Crush your walnuts
* Add walnuts, honey, cocoa powder and stir until combined and smooth
* Put into the microwave for 3 minutes or until not gooey on 800W 🍰 - Have delicious healthy meal made in ~5 minutes, happy coding 💻
PS - We never said the treat had to be relevant to the post 😛
Sources
- https://marketplace.visualstudio.com/items?itemName=humao.rest-client
- https://stackoverflow.com/a/66343248/3094496
- https://medium.com/@erbo-engineering/how-to-run-firebase-emulator-without-a-hassle-a819805a034
- https://firebase.google.com/docs/reference/rest/auth
- https://cloud.google.com/identity-platform/docs/use-rest-api
- https://code.visualstudio.com/
Follow us for more articles in the near future. 🚀
We plan to publish an article at least once a month containing all kinds of interesting tech topics. Ranging from “Improving your development environment” to “Introduction into embedded Linux” and many more.