Cloud Functions for Firebase HTTP Request - firebase

I want to send an HTTP Request from Android to a cloud function, post some values, then input these values into real time database.
index.js
const functions = require('firebase-functions');
exports.testPost = functions.https.onRequest((req, res) => {
console.log(req.body);
});
How can I accomplish this?

I see three steps in here:
Calling a Cloud Function from Android.
This is the same as calling any other HTTP URL from Android. See
Calling a Cloud Function from Android through Firebase
Parsing parameters from the call in your Cloud Function
A HTTP triggered Cloud Function is really just an Express handler. So parsing the post works the same as for other Express handlers. The Firebase documentation for HTTP functions has some examples and links to other documentation.
Posting to the database from a Cloud Functions
All the samples in the functions-samples repo include the Firebase Admin SDK. This SDK allows you to access many Firebase features, such as the database, from within your function. But there's also an example in this repo.

Related

How to call Firebase Cloud Function that uses ExpressJS with cloud_functions

I have a Firebase Cloud Function setup with ExpressJS which I would like to call call from my app.
I could of course just do an http request but since there is an cloud_firestore package (dart/Flutter) I thought that would be the best way to go, guessing it would handle the authentication for me.
The endpoint is just an express app:
const app = express();
app.post('/message', async function (req:any, res: any) {
...
other code
...
}
In my Flutter app I do:
final HttpsCallable addMessage = new CloudFunctions(region: "us-central1")
.getHttpsCallable(functionName: 'api');
addMessage.call();
This will return a NOT_FOUND error, probably because I have to pass in the path for ExpressJS.
But I have not a clue about how to do that.
The Firebase callable functions client library does not work with arbitrary HTTP endpoints. It's meant to work only with callable functions that you write according to the documentation.
If you have a standard HTTP endpoint, just use a regular HTTP client library for that.
If you want to pass Firebase Auth credentials along with the request, there are some examples of that in the Firebase Admin SDK documentation. (You use the Admin SDK to verify the credentials passed from the client app.)

Nexmo: Receiving SMSes

As one new to Nexmo, I found an easy way to receive SMSes using Firebase here.
After initialising Firebase with:
firebase init functions
you write into the generated index.js:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.inboundSMS = functions.https.onRequest(async (req, res) => {
await admin.database().ref('/msgq').push(req.body);
res.send(200);
});
Then you deploy the code to Firebase with:
firebase deploy --only functions
which yields a callback URL (webhook) similar to:
https://us-central1-nexmo-project.cloudfunctions.net/inboundSMS
By adding the above URL in the API settings of the Nexmo Dashboard, the messages will be grabbed by Firebase DB.
Now I have two questions.
The first is a licencing problem: the author claims that the Firebase "Pay-as-you-go plan is required to use a third-party API". What does this mean? Isn't the webhook consumer always a third party? I don't find any useful hint on Firebase site.
The second question regards securing the callback URL. It seems that everyone can send data through the URL, so how can I avoid spamming and peruse of the URL?
Glad you found my post useful.
To answer your questions -
If you are using Nexmo to send an SMS, or any other service that would require you to call a 3rd party API, you would need to use the pay-as-you-go from Firebase. If you only want to use it as a webhook that would be called from an external source into Firebase, the free tier should be usable. The difference is in the calling external APIs. Google provides a better explanation of this type of call - https://firebase.google.com/docs/functions/use-cases#integrate_with_third-party_services_and_apis. Google network calls shouldn't be included in this - one of the benefits of using Firebase.
Securing the webhook has a couple of options. The first is, it's not an easily discoverable URL, so keeping it private should be the initial line of defense. Nexmo also has a list of IP's that can be whitelisted here - https://help.nexmo.com/hc/en-us/articles/204015053. In the headers you should be able to locate the IP and verify it before allowing it to do anything else, or just kick it out completely.
Let me know if that helps!

How to notify a Firebase Admin SDK user using a cloud function?

I am a student developing an app and I have some back-end python code that utilizes the Firebase admin SDK. The app with provide an interface to an proprietary algorithm that cannot be moved into the a cloud function and so must stay within the back-end server. When a user makes a request to the algorithm, they will do so by uploading a document to Firestore with information the back-end needs to process their request.
Once a user uploads a document, an onCreate() cloud function is triggered, the goal of this function is to simply notify the back-end that there is a pending request, so that it can process it and send back to the user.
This is where I am struggling, I haven't been able to deduce a way to trigger action on the back-end from within the cloud function. I am hoping to find a way to accomplish this through Firebase without the need to implement additional libraries etc.
A way to generalize my issue would be:
How would you notify an Firebase Admin SDK user through a Cloud Function?
FCM is used for sending messages and notifications to mobile clients. It doesn't work for sending messages to backend components.
If you want to notify some backend component, you typically use an HTTP endpoint or pubsub messaging.
Firebase Functions SDK already uses the Firebase Admin SDK under the hood. So if you set up a Cloud Functions trigger in Node.js, you can access Admin SDK from the Function itself. For instance, taking a Cloud Storage trigger as an example:
const admin = require('firebase-admin');
admin.initializeApp();
exports.fn = functions.storage.object().onFinalize((object) => {
// Call Admin SDK APIs
});
Similar integrations should be possible with Python as well: https://medium.com/#hiranya911/firebase-using-the-python-admin-sdk-on-google-cloud-functions-590f50226286

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.

Slack API Event Subscription to trigger Firebase Cloud Functions

Goal
I would like Slack to trigger a Firebase Cloud Function.
Example: A user sends a Slack message, and Firebase Cloud Functions writes part of the message to the Firebase Database.
Tools: Slack API \ Event Subscription, googleapis, nodejs, etc.
Issue
The Slack documentation here describes the challenge response requirement.
Once you receive the event, respond in plaintext with the challenge
attribute value.
However, I'm not sure how to let Firebase know the Slack request is authorized. An HTTP request to Firebase Cloud Functions must include a Firebase ID. I've let googleapis do the work of setting up the Firebase ID, and I don't see a way to alter Slack's initial verification request (if I had an ID to provide)
What's the best way to trigger Firebase with the Slack API?
Getting Slack to verify the Firebase URL is pretty easy.
Solution
Google Firebase Cloud Function
import * as functions from "firebase-functions";
export const helloSlack = functions.https.onRequest((request, response) => {
if (request) {
response.status(200).send(request.body);
} else {
console.log("Request Error...");
throw response.status(500);
}
});
Steps
Deploy your Firebase Cloud Function
Goto https://api.slack.com/apps
Your App > Event Subscriptions > Enable Events
Turn on Events
Enter your Firebase Cloud Functions URL
tl;dr
Slack instructions:
We’ll send HTTP POST requests to [your] URL when events occur. As soon
as you enter a URL, we’ll send a request with a challenge parameter,
and your endpoint must respond with the challenge value.
Cloud Function URL:
https://firebase-slack-adaptor.cloudfunctions.net/helloSlack
To meet the verification challenge, enter your Firebase Cloud Functions URL (example above) in Slack's Request URL field.
Your Firebase Cloud Function should return the body of the Slack request. Slack finds what it needs in request.body and should verify your URL.

Resources