I have a firebase project that I use as the backend of a flutter application. The authentication process is managed by Firebase Authentication and I use callable cloud functions to perform some tasks.
A few days ago, I realized I was using 1st generation cloud functions and I decided to switch to 2nd generation cloud functions. After doing that, all the callable cloud functions stopped working giving the error [firebase_functions/unauthenticated] UNAUTHENTICATED. The code used to call the function in the client side is the following:
FirebaseFunctions functions = FirebaseFunctions.instanceFor(region: 'europe-west1');
final HttpsCallable functionExample = functions.httpsCallable('functionExample');
functionExample.call().then((result) {
debugPrint('Function successfull');
})
where FirebaseFunctions is from cloud_functions flutter library.
After some investigation, I have understood that the error is caused because in 2nd generations cloud functions the functions are deployed and run inside Google Cloud so the Firebase authenticated user from the flutter client app is not a valid google cloud user and that’s why I get the Unauthenticated error message.
Then my question is how can I overcome this but still keeping it secure. I know I can give Cloud Functions Invoker Role to "allUsers" in the permissions of the function in google cloud in order to be callable for everybody but I would like to keep an approach where the function requires authentication but a Firebase authenticated user is valid.
I am thinking on generating a token for the Firebase authenticated user which is valid for google cloud or even making google cloud aware of the Firebase users and treat them as google cloud users.
I would also like to avoid a hardcoded check inside the cloud function in order to see if the user has a firebase valid token.
Hope someone has faced the same issue and worked it out in a way where the call is not made accessible for everyone.
EDIT: I just noticed I am using Identity Platform so I have the users also in Google Cloud, how can I then authenticate the users through Identity Platform. Do I need to stop using Firebase Authentication and use another library which targets directly GCP?
2
Answers
Google Cloud Identity Platform and Firebase Authentication are using the exact same infrastructure behind the scenes. They share the exact same user database, and the only difference is in pricing and feature set. So if your Firebase project has existing users, those will show up in Cloud Identity Platform too (and vice versa).
Cloud Functions Invoker Role to "allUsers" is absolutely necessary for callable type functions that are invoked from web and mobile frontends. You should be aware that GCP "allUsers" doesn’t have anything to do with Firebase Auth users signing into your app. It’s a GCP IAM role that indicates that the function can be invoked without the permission of a service account (which is indeed what you’re trying to do here).
If you want to control what a Firebase Auth user may or may not accomplish with your callable function, you need to write some code in that function to check the Firebase Auth user that invoked the function, and decide what they are allowed to do. A brief example of this is provided in the documentation:
So, using the data provided in
request.auth
, you should be able to find out which user invoked the function from your web or mobile app and decide what they are able to accomplish.If your function happens to be a normal HTTP type function (not a callable), then your app needs to pass along some sort of Firebase Auth user ID token to the function so that it can verify the token and make decisions from there. The function still needs "allUsers" permission to allow it to be invoked directly by your app.