4

I have a Node.js API (built with Express.js) hosted on Firebase Cloud Functions and an accompanying web application hosted on Firebase Hosting which is supposed to interact with the aforementioned API.

I would like to restrict calls to the API so that only the web application would be able to call the cloud functions. How can I achieve that?

What I have tried:

  • using the App Check or more precisely Google's reCAPTCHA v3 for web apps. I have whitelisted the domain of the web application and have activated App Check token validation server side as well. The problem with App Check, however, is that I am able to obtain the reCAPTCHA attestation token from the browser (after authenticating through the web app) and use that with requests made from anywhere. This enables bombarding the API from outside the web application and defeats the purpose of using App Check in the first place.

    Something to note here, the documentation for activating App Check in Cloud Functions instructs the usage of functions.https.onCall(). However, since my API is built using Express.js, I had to use a workaround to be able to use functions.https.onRequest() as instructed here.

  • restricting the Cloud Function from Google Cloud console to allow only clients of the same project to call the function as instructed here. Unfortunately, my web application hosted on Firebase Hosting does not seem to belong under the same Google Cloud project. Apps hosted on Firebase Hosting do not appear in Google Cloud console. Furthermore, after adjusting the Ingress settings of the functions to "allow internal traffic only", I am receiving CORS errors when attempting to access the API through the web application. I am unable to access the API from anywhere else though, which is partly the desired outcome.

Before anyone proposes limiting the domains in CORS options from within the API, while this might serve the purpose of restricting access to the API endpoints, it still would allow calling the function rapidly and thus, potentially, racking up the bill.

I am grateful for any suggestions!

robila
  • 43
  • 4
  • If you're not satisfied with App Check, then you have no other options. You simply can't restrict traffic in the way that you describe. All generalized backend services have the same issue - it's just the way the internet works. Any server endpoint can be abused if you're not able to restrict the access based on source IP, and even that can be faked. – Doug Stevenson Sep 22 '21 at 21:17
  • Note also that the token you get from App Check has an expiration, so it can't be used indefinitely. This is covered in the documentation. An attacker would have to keep getting new tokens for as long as they want to abuse the endpoint. Do you have something in your backend that is worth all the effort? – Doug Stevenson Sep 22 '21 at 21:25
  • Thank you for the clarification. What bugs me is the ease of such a potential abuse - authenticating, obtaining the app check token and bombarding the API with a 3 line script is not that big of an "effort". I guess a rate limit would help in such case to minimize the damage, although creating internal rate limit within the API would still mean the function is being triggered (potentially resulting in a racked up bill). I'm not necessarily protecting state secrets in my API but it's best to prepare for the worst, isn't it? – robila Sep 24 '21 at 14:34
  • The ease of attack is the reason why cybersecurity is a multi billion dollar industry. When you get to the point of being a large and desirable target, then you're able to spend lots of money on sophisticated solutions that control the traffic to your site in order to manage costs and mitigate risks. Cloud Functions (on its own terms) is not a sophisticated product in that sense, so if you're worried about attacks, you should consider a major upgrade in your backend infrastructure using products like [Cloud Armor](https://cloud.google.com/armor). – Doug Stevenson Sep 24 '21 at 14:47

1 Answers1

1

Firebaser here.

This is a great question! Doug has already made some great points above, and I'll just add to that by saying that the TTL on App Check tokens reduce the replay window that you observed in your first bullet point, and this TTL is configurable.

The default TTL for reCAPTCHA v3 is 1 day to protect against running out of quota, but you can set a shorter TTL to increase the cost for an attacker trying to set up a replay attack. But please do be mindful of the associated trade-offs as described in the documentation. You can read about the associated quotas and limits here.

Unfortunately, web applications redirected from Firebase Hosting can't hook up to the GCP internal network. App Check is actually exactly what you are looking for in this situation.

Finally, because we are continuously working on improving the App Check platform, the comments you leave here are valuable for us as we decide on what anti-abuse features we want to work on next.

Victor Fan
  • 180
  • 5
  • Thank you for the clarification. Will the Firebase Hosting websites gain the ability to "hook up to the GCP internal network" in the future? Additionally, would it be possible to configure an IP-based rate limit to the Cloud Functions (before the function handles the request)? – robila Sep 24 '21 at 14:41