Firebase Callable Function, restrict invoke to APP [duplicate] - firebase

Firebase callable cloud functions can be accessed via client sdks, which requires a valid auth context for authentication and authorization. But and at the same time it is exposed as an HTTP endpoint, thus can be called but will receive an unauthorized response.
My questions is, is there a way to completely restrict public access for a callable cloud functions? since firebase will charge cloud functions based on function executions. Even to return an unauthorized response, the request has already gone through to the function, thus during a DDoS attack this could be problematic.

There is no built-in support for rejecting a request to a Cloud Function before it reaches your code. If you want such functionality consider setting up Cloud Endpoints in front of your Cloud Functions.
The best you can with just Cloud Functions do is check whether the caller is authorized as the first thing in your function code, so that you reduce the amount of time the function is active. You'll still be charged for the invocation in that case, but you'll minimize the GB-seconds and CPU-seconds.

I tried out as #Frank suggested using google cloud run to deploy and ESP container which can by used to invoke private cloud functions. A detailed overview is described in the documentations itself.
https://cloud.google.com/endpoints/docs/openapi/get-started-cloud-functions#deploy_endpoints_proxy

Above given answer by #Frank van Puffelen is perfect but you can utilize a trik to restrict the access by securing that route. Here is the example,
const functions = require('firebase-functions');
exports.scheduleSampleJob = functions.https.onRequest((req , res) => {
let auth = req.header('Authorization');
if(auth == 'YOUR_API_AUTHORIZATION_KEY'){
// valid Authorization key, process the call
}else{
//send forbidden if Authorization key not valid
return res.status(403).send('Access is Forbidden');
}
});
Now, if you want to call the endpoint, It will require a Authorization header in request having value your secret key.
As firebase cloud function can also be used with firebase-auth, you can create custom logic to allow access to users having auth only and restrict the access for public excluding your app's authentic users.

Related

Is it possible to only allow authenticated users to use callable function, without getting billed for invalid invocations?

I have a callable function that gets users auth data and validates it (inside the function), if user is not authenticated or allowed to do a certain action I throw respective error.
However nothing stops malicious actors to run a loop that constantly pings such function and rack up cost in terms of invocations / little bit of time those functions run.
Cloud providers like AWS have systems in place where this auth check is set up on an api gateway / loadbalancer level and users are not billed if someone calls functions with unexpected headers / payload or without authentication.
Does something like this exist for firebase, perhaps via google cloud?
No, it's not possible. The callable function must execute in order for the firebase-functions SDK to verify the user's ID token via the Firebase Admin SDK. It's not a "free" operation in any way. No matter how you write or deploy it, something is going to have to invoke the Firebase Admin SDK to verify the token - it's not part of any unbilled cloud infrastructure.

Firebase HTTPS callable functions being called by unauthenticated end users

I have doubts on the calling of firebase functions (gcp functions).
According to here: https://firebase.google.com/docs/functions/callable,
when HTTPS callable functions are being called, the functions.https.onCall trigger automatically deserializes the request body and validates auth tokens. Then in this case, if an unauthenticated end user called this function, is this function being triggered or not? In other words, will I be charged on this calling?
Its true that it does validate the auth tokens for you, but what your function does with those auth tokens is up the the function. By validating them, the framework ensures that invalid auth tokens won't look like an authenticated user.
Notably, the documentation states:
With callables, Firebase Authentication and FCM tokens, when available, are automatically included in requests.
The key to your question is when available.
If validating that the request was authenticated is important to you, then you need to check the variables that firebase provides in the context parameter. (See the API definition of the CallableContext object that is passed in. You are able to pull things off such as the uid (as auth.uid on the second parameter to the function), etc.
In short, the function certainly is executed, and if it does anything or not for an unauthenticated user depends on how it is written.
You can safely expect that the invocation itself is still is accounted for in your free tier quota or as a billable invocation -- there isn't anything at all that says that callable functions have to be authenticated, and there are many possible uses for non-authenticated callable functions (e.g. you want to protect a certain part of the database to only be accessed by server-side code, even if unauthenticated users run it).

Is there a way to restrict public access from firebase callable could functions

Firebase callable cloud functions can be accessed via client sdks, which requires a valid auth context for authentication and authorization. But and at the same time it is exposed as an HTTP endpoint, thus can be called but will receive an unauthorized response.
My questions is, is there a way to completely restrict public access for a callable cloud functions? since firebase will charge cloud functions based on function executions. Even to return an unauthorized response, the request has already gone through to the function, thus during a DDoS attack this could be problematic.
There is no built-in support for rejecting a request to a Cloud Function before it reaches your code. If you want such functionality consider setting up Cloud Endpoints in front of your Cloud Functions.
The best you can with just Cloud Functions do is check whether the caller is authorized as the first thing in your function code, so that you reduce the amount of time the function is active. You'll still be charged for the invocation in that case, but you'll minimize the GB-seconds and CPU-seconds.
I tried out as #Frank suggested using google cloud run to deploy and ESP container which can by used to invoke private cloud functions. A detailed overview is described in the documentations itself.
https://cloud.google.com/endpoints/docs/openapi/get-started-cloud-functions#deploy_endpoints_proxy
Above given answer by #Frank van Puffelen is perfect but you can utilize a trik to restrict the access by securing that route. Here is the example,
const functions = require('firebase-functions');
exports.scheduleSampleJob = functions.https.onRequest((req , res) => {
let auth = req.header('Authorization');
if(auth == 'YOUR_API_AUTHORIZATION_KEY'){
// valid Authorization key, process the call
}else{
//send forbidden if Authorization key not valid
return res.status(403).send('Access is Forbidden');
}
});
Now, if you want to call the endpoint, It will require a Authorization header in request having value your secret key.
As firebase cloud function can also be used with firebase-auth, you can create custom logic to allow access to users having auth only and restrict the access for public excluding your app's authentic users.

Firebase Cloud Functions setting environment configuration within a cloud function

I'm using cloud functions that call an external service that uses OAuth2 Security. Each invocation of my cloud function first, authenticates and gets an access token for the subsequent API call to the external service.
The access token expires in 30 mins, so to avoid token expiration, each invocation I get a new token.
I'd like to use the cloud function scheduler to get the access token and save it to the cloud function config, I can schedule this to happen every 25 mins. This would avoid each invocation requiring to first get an access token.
It does not look like the cloud function environment config allows programmatic updating of config within a cloud function.
https://firebase.google.com/docs/cli/#functions-commands
Anyone solved something similar?
UPDATE: As following further docs, the cloud function needs to be deployed again for the configuration update to occur. I think the solution to this question is likely a CI cronjob, that gets an access token, updates firebase cloud function configuration and redeploys the cloud functions.
I think that trying to update the configuration of the function, or redeploying the function altogether, isn't really the best idea here. You're probably better off just storing the information in a database or some other shared location, then each function can query that to get a hold of the token and its metadata as needed. The function can store the token in memory for as long as its known to be valid so that it doesn't have to be fetched for each invocation.

get Response from Firebase cloud functions

I've created a cloud functions in firebase and I want to get response of the functions back to Android app.
Cloud functions is written in typescript and is like
exports.validateOtp = functions.https.onRequest((req,res)=>{
phoneNumber = req.query.phoneNumber;
otp = req.query.otp;
getVal();
function getVal(){
let result = authFunction.userValidation(phoneNumber,otp).then(function(boolResult){
return res.status(204).send(result);
});
}
});
How can I fetch the value of result at client side or android app?
Since your Cloud Function is an HTTPS one it will be triggered when you send an HTTP request (GET, POST, PUT, DELETE and OPTIONS) to the function endpoint.
In your case the function endpoint URL will be
https://us-central1-<your-project-id>.cloudfunctions.net/validateOtp
see https://firebase.google.com/docs/functions/http-events#invoke_an_http_function
There are several possible ways to send an HTTP request from an Android app to an HTTP endpoint. You could use the Volley library, the android-async-http library or the Retrofit one, for example.
Note that it may be interesting to switch to an HTTPS Callable Cloud Function instead of a "simple" HTTPS Cloud Function.
As explained in the doc, "the Cloud Functions for Firebase client SDKs let you call functions directly from a Firebase app. To call a function from your app in this way, write and deploy an HTTPS Callable function in Cloud Functions".
Among the advantages offered by HTTPS Callable functions you will find the fact that it "automatically deserializes the request body", that it "validates auth tokens" as well as the fact that you don't need to use an extra library to call the Function, but just to use the code detailed in the doc.

Resources