Have deployed a few firebase functions (according to docs)
firebase init
Changed the code to something like
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.getUsers = functions
.region('europe-west1')
.https.onRequest((req, res) => {
admin.firestore().collection('users').get().then(data => {
const users = data.map(user => user.data());
return res.json(users);
}).catch(err => console.error(err));
});
exports.helloWorld = functions.https.onRequest((req, res) => {
res.status(200).send('Hello, World!');
});
Deployed it.
firebase deploy
And as an end result both of the functions return
Error: Forbidden Your client does not have permission to get URL
/getUsers from this server.
Error: Forbidden Your client does not have permission to get URL
/helloWorld from this server.
In the firebase admin console I see that functions exist, and they are there, and I am using same exact urls that the terminal gave me & are on the firebase admin console.
Any ideas?
PS. Located in Estonia.
Alright,
To solve this issue I had to use my brain and check the dashboard for cloud functions. Cloud functions do not return a 500 error unlike most common APIs, instead inside of the dashboard I found out that:
TypeError: data.map is not a function
admin.firestore.collection.get.then.data ( /user_code/index.js:10 )
Meaning my 'application' was crashing, oddly enough it was giving me a 403 error.
For good measure I also followed this:
Firebase cloud function "Your client does not have permission to get URL /200 from this server"
Related
I am calling a simple firebase function from a web app I get an INTERNAL error. Can someone please suggest where I could be going wrong.
I have seen similar questions but they don't answer the issue I am facing.
I can confirm that the function has been deployed to the firebase.
By pasting the below link in the browser I get a response.
https://us-central1-cureme-dac13.cloudfunctions.net/helloWorld
index.js file has the code (Firebase cloud functions are defined in index.js)
const functions = require('firebase-functions');
exports.helloWorld = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase!");
});
webApp.js has the below code (Client/Website)
var messageA = firebase.functions().httpsCallable('helloWorld');
messageA().then(function(result) {
console.log("resultFromFirebaseFunctionCall: "+result)
}).catch(function(error) {
// Getting the Error details.
var code = error.code;
var message = error.message;
var details = error.details;
// ...
console.log("error.message: "+error.message+" error.code: "+error.code+" error.details: "+error.details)
// Prints: error.message: INTERNAL error.code: internal error.details: undefined
});
You are mixing up Callable Cloud Functions and HTTPS Cloud Functions.
By doing
exports.helloWorld = functions.https.onRequest(...)
you define an HTTPS Cloud Function,
but by doing
var messageA = firebase.functions().httpsCallable('helloWorld');
messageA().then(function(result) {...});
in your client/front-end, you actually call a Callable Cloud Function.
You should either change your Cloud Function to a Callable one, or call/invoque the helloWorld HTTPS Cloud Function by sending an HTTP GET Request to the Cloud Function URL (Similarly to the way you did in your browser by "pasting the https://us-central1-cureme-dac13.cloudfunctions.net/helloWorld link in the browser").
For example, by using the Axios library, you would do:
axios.get('https://us-central1-cureme-dac13.cloudfunctions.net/helloWorld')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
I am trying to send one to one notification from android device using Firebase Cloud Messaging service and code in Fireabse CLI. But I am failing to deploy the code due to parsing error, which I cannot figure out.
My idea is as follows: For security reasons, I understand, I need to use Firebase Cloud functions to send notification. From my android code I will be writing the target device's token, message body and topic in Firebase database. As soon as the write event occurs, the Firease function would get deployed to send the notification. Here is my Firebase code
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/Notification/{receiver_token}/{message_topic}/{message_body}’).onWrite((data, context) =>
{
const receiver_token = context.params.receiver_token;
const message_topic = context.params.message_topic;
const message_body = context.params.message_body;
console.log('We have a notification to send to token: ’ , receiver_token);
const payload =
{
notification:
{
title: message_topic,
body: message_body,
icon: "default"
}
};
return admin.messaging().sendToDevice(receiver_token, payload)
.then(response =>
{
console.log('This was a notification feature.');
});
});
When I am trying to deploy this function in Firebase, I am getting the following error:
error Parsing error: Unterminated string constant
Error: functions predeploy error: Command terminated with non-zero exit code1
I can provide the complete error log if needed
This line of code looks like a problem:
console.log('We have a notification to send to token: ’ , receiver_token);
Your beginning quote is a single quote (apostrophe), but your end quote is a different quote mark. Look at them very carefully. Make the second one match the first one.
I am using the Node.js Admin SDK within a Cloud Function for Firebase and I want to call the admin.auth().getUserByEmail() method.
Since I'm using a Cloud Function I read here that I only need to call admin.initializeApp(functions.config().firebase); which you can see below I've done.
However, when I call the getUserByEmail() (only tested locally) I get the following error:
'No Firebase project was found for the provided credential.'
Here's my index.js
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.hello = functions.https.onRequest(function (req, resp) {
var from = req.body.sender;
admin.auth().getUserByEmail(from)
.then(function (userRecord) {
// See the UserRecord reference doc for the contents of userRecord.
console.log("Successfully fetched user data:", userRecord.toJSON());
})
.catch(function (error) {
console.log("Error fetching user data:", error);
})
});
Has anyone got any experience of this and can tell me what I'm doing wrong?
The admin sdk won't get proper config json if you are using localy(in google cloud functions emulator). You have to use your service account json obtained from firebase console.
But if you have deployed it, your method will work just fine.
Is there a way to check if a user is firebase-authorized before triggering a cloud function? (Or within the function)
Yes. You will need to send the Firebase ID token along with the request (for example in the Authorization header of an AJAX request), then verify it using the Firebase Admin SDK. There is an in-depth example in the Cloud Functions for Firebase samples repository. It looks something like this (made shorter for SO post):
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const cors = require('cors')();
const validateFirebaseIdToken = (req, res, next) => {
cors(req, res, () => {
const idToken = req.headers.authorization.split('Bearer ')[1];
admin.auth().verifyIdToken(idToken).then(decodedIdToken => {
console.log('ID Token correctly decoded', decodedIdToken);
req.user = decodedIdToken;
next();
}).catch(error => {
console.error('Error while verifying Firebase ID token:', error);
res.status(403).send('Unauthorized');
});
});
};
exports.myFn = functions.https.onRequest((req, res) => {
validateFirebaseIdToken(req, res, () => {
// now you know they're authorized and `req.user` has info about them
});
});
Since the question asks for auth-based access (1) within, or (2) before a function, here's an method for the "before" case: >
Since every Firebase Project is also a Google Cloud Project -- and GCP allows for "private" functions, you can set project-wide or per-function permissions outside the function(s), so that only authenticated users can cause the function to fire.
Unauthorized users will be rejected before function invocation, even if they try to hit the endpoint.
Here's documentation on setting permissions and authenticating users. As of writing, I believe using this method requires users to have a Google account to authenticate.
I just configured my first Cloud Functions for Firebase and after deploying the index.js file and upload all the changes to my server. I'm trying to use one of my functions which is a simple HTTP request to create a field on a table in my Firebase Database:
const functions = require('firebase-functions');
exports.addMessage = functions.https.onRequest((req, res) => {
// Grab the text parameter.
const original = req.query.text;
// Push it into the Realtime Database then send a response
admin.database().ref('/messages').push({ original: original }).then(snapshot => {
// Redirect with 303 SEE OTHER to the URL of the pushed object in the Firebase console.
res.redirect(303, snapshot.ref);
});
});
But when I'm calling to my request on my browser I'm receiving an error on my Functions console which says admin is not defined:
What might be causing this error?
You need to import the Admin SDK module just like you are importing the Cloud Functions SDK:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
Example code can be found here. This is also covered in the "get started" guide.