since 28-03-2020 all my HTTP cloud functions are in error. Before my last update, they were working fine. I changed only few things and after the last deploy I got this error:
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>403 Forbidden</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Forbidden</h1>
<h2>Your client does not have permission to get URL <code>/api/v0/.../</code> from this server.
</h2>
<h2></h2>
</body>
</html>
All the changes I did doesn't refer to the HTTP function implementation only in the BI.
Is there someone else with the same error? From the Firebase Status Console, it seems that firebase is not experiencing any error https://status.firebase.google.com/
EDIT: added an extract on how I initialize the HTTP cloud functions.
'use strict';
// node import
const cors = require('cors')({ origin: true });
const functions = require('firebase-functions');
const admin = require('firebase-admin');
// Setting timeout and memory for the deploy
const runtimeOpts = {
timeoutSeconds: 540,
memory: '2GB'
}
admin.initializeApp();
exports.exportMultipleDataToCSV = functions
.runWith(runtimeOpts)
.https.onRequest((request, response) => {
cors(request, response, () => {
if (request.method === 'PUT') response.status(403).send('Forbidden!');
if (request.method === 'DELETE') response.status(403).send('Forbidden!');
if (request.method === 'POST') response.status(403).send('Forbidden!');
// BI
let data = MY-BI;
response.status(200).set('Access-Control-Allow-Origin', '*').send(data);
});
});
I'm using the library "request" that I just saw that has been deprecated 2 months ago. It could be the problem? https://www.npmjs.com/package/request
Cloud Functions recently changed their default IAM policies for new functions to be restricted to project owners (previously it was allUsers, which allows for public access).
To prepare for this change, firebase-tools#7.7.0 added an IAM policy update on function creation that adds allUsers permissions. If you are using an older version of the CLI, new functions might be deployed in a restricted mode.
Importantly, however, this change should only apply to the creation of new functions -- if a function already exists and was only updated, no IAM changes should occur. If you're experiencing something else when updating functions, please file a detailed issue including debug logs with firebase-tools.
Related
I am developing a google chrome extension with manifest version 3 using Firebase and Firestore for store user data.
When I try to write on the Firestore i'll get this error: Uncaught ReferenceError: XMLHttpRequest is not defined
My firebase-main.js looks like this:
import "/firebase-app.js";
import "/firebase-auth.js";
import "/firebase-firestore.js";
try {
const firebaseConfig = {
apiKey: "MYDATAHERE"
authDomain: "MYDATAHERE",
projectId: "MYDATAHERE",
storageBucket: "MYDATAHERE",
messagingSenderId: "MYDATAHERE",
appId: "MYDATAHERE"
};
console.log("firebase main inizializing");
const app = firebase.initializeApp(firebaseConfig);
console.log(app);
const db = firebase.firestore();
console.log(db);
chrome.runtime.onMessage.addListener((msg, sender, resp) => {
console.log("msg.command = " + msg.command);
if(msg.command == "post"){
console.log("msg = post");
console.log("msg.data.extensionEmail is " + msg.data.extensionEmail);
db.collection("users").doc(msg.data.extensionEmail).set({
data: msg.data
})
.then(function() {
console.log("Document successfully written!");
})
.catch(function(error) {
console.error("Error writing document: ", error);
});
}
sendResponse(true);
return true;
})
} catch (e) {
console.error(e);
}
Inside my extension popup.js i'll send the message to firebase-main and the message is received but when it try to write on Firebase the error comes out.
I am using firebase-app, firebase-firestore and firebase-auth 8.5 downloaded inside the main directory of the extension.
I read that XMLHttpRequest is no more supported with service worker in manifest version 3 but I can't find a way to write on the db.
Can anyone help me please?
I've already tryed to import xhr2 using the command npm install xhr2 and import at the top of firebase-firestore.js without success.
I've tryed using newer/older versions of firebase-app, firebase-firestore and firebase-auth.
ServiceWorkers in Chrome Extensions using Manifest V3 can no longer access XMLHTTPRequest and instead use fetch(). This means that you may have to find a polyfill for it, however, this does come with some inherint challenges once you do find a polyfill. One challenge is that XHR synchronous operations cannot be replicated in fetch completely since fetch is an asynchronous API by design. Additionally, you would need to place some trust in the authors of the polyfill that they are not doing anything nefarious with their polyfill library that you are using. If I was you, I would determine what functionality you are looking to use in Firestore and either call a cloud function from an HTTPS endpoint with the firebase functions you want or, if you are interested in querying firestore, utilizing the REST API and the fetch API to make those commands.
This question already has answers here:
Firebase Callable Function + CORS
(21 answers)
Closed 1 year ago.
I have a problem with Firebase and CORs, apparently it cannot reach the endpoint with errors like:
Access to fetch at
'https://europe-west2-XXX.cloudfunctions.net/fetchChatToken'
from origin 'https://trato.app' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. If an opaque response serves your needs, set the request's
mode to 'no-cors' to fetch the resource with CORS disabled.
service.ts:203
POST
https://europe-west2-XXX.cloudfunctions.net/fetchChatToken
net::ERR_FAILED (anonymous) # service.ts:203 ... ...
error.ts:66 Uncaught (in promise) Error: internal
at new t (error.ts:66)
at error.ts:175
at e. (service.ts:276)
at tslib.es6.js:100
at Object.next (tslib.es6.js:81)
at a (tslib.es6.js:71)
I also checked the network tab on dev inspector (chrome) to check if the CORS header is there, i dont see it.
Also, I have been checking firebase functions logs and apparently is not being even invoked, the last line showing is the deployment.
the way that Im using it is this:
Front End side:
const functions = firebaseApp.functions('europe-west2');
export const fetchChatToken = async () => (await functions.httpsCallable('fetchChatToken')()).data;
Functions (Backend) side:
const ensureAuthentication = auth => { if (!auth) throw new HttpsError("unauthenticated", "authentication required"); };
exports.fetchChatToken = functions.region("europe-west2").https.onCall((data, context) => {
ensureAuthentication(context.auth);
try {
const { AccessToken } = twilio.jwt;
const { ChatGrant } = AccessToken;
const grant = new ChatGrant({
serviceSid: conversationsid
});
const token = new AccessToken(accountsid, apikey, apisecret);
token.addGrant(grant);
token.identity = context.auth.uid;
return token.toJwt();
} catch (error) {
console.error(error);
throw new HttpsError("internal", "internal error");
} });
Unfortunately there many reasons possible for this CORS error. If the cloud function returns an "internal" error message it might be due to inconsistent Regions or errors in your cloud function code. My checklist for this error when creating a new cloud function:
Not matched Regions of Firestore-Project, Functions and Client side init cause a CORS Error
internal code errors inside the cloud functions cause this error
new function must be included in cloud function index file (if used)
cloud function name must match the string on client side invocation
delete cloud function in firebase dashboard before deploying new one after error
Make sure the function name referenced in the client is correct, see https://stackoverflow.com/a/62042554/1030246
I got it solved changing it to us, basically removing the region, taking out the 'europe-wes2' region from the function declaration and from the function call it works fine again.
I assume there is some error on the firebase side.
This looks to be pretty obvious but I've been trying to figure it out for a couple of days now and still can't get it to work. Please, can someone point out what I'm missing.
I'm trying to make an axios call to my cloud run service from my firebase hosted SPA. To isolate the issue I followed the steps outlined in the [firebase tutorial for cloud run] (https://firebase.google.com/docs/hosting/cloud-run#node.js)
Step 4 of the tutorial talks about setting up rewrite to use the firebase domain as a proxy to your cloud run service. It says that the helloworld service would be reachable via
Your Firebase subdomains:
projectID.web.app/helloworld and projectID.firebaseapp.com/helloworld
So I follow the steps and deploy the service. Then I try to make an axios call to the service from the SPA like below
testHelloWorld () {
axios.get(`https://myProjectId.firebaseapp.com/helloworld`)
.then((data) => {
console.log(data)
})
.catch(ex => {
console.error(ex)
})
})
}
But then I get the CORS error
Access to XMLHttpRequest at 'https://myProjectId.firebaseapp.com/helloworld' from origin 'https://myFirabaseApp.firebaseapp.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
This answer states that this should be possible so I'm not sure what I'm doing wrong.
N.B:
While debugging, I updated the node app from the tutorial to add cors support like below. Still didnt work.
const express = require('express');
const app = express();
const cors = require('cors'); //Imported and added this
app.use(cors()); // Used here
app.get('/', (req, res) => {
console.log('Hello world received a request.');
const target = process.env.TARGET || 'World';
res.send(`Hello ${target}!`);
});
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log('Hello world listening on port', port);
});
So the question here is, how do I make an Axios/AJAX call to my cloud run service using the firebase rewrite rule?
Please check if you have installed cors: npm install cors.
Please check if the 2 following options can solve your issue:
1= Use the following code :
app.use(cors({origin:true,credentials: true}));
2) If the previous didn't work, please use the following code:
app.get('/', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
console.log('Hello world received a request.');
}
Please let me know if it works for you.
I'm trying to get my Cloud Functions for Firebase to call a simple web app deployed using Google Apps Script. Can someone please point to any example or help figure out whats the reason for the error in my code below. Really appreciate your help.
--
I've created a simple webapp with Google Apps Script.
function doGet() {
return ContentService.createTextOutput('Hello world');
}
And I'm calling this using request-promise within my Firebase Cloud Function. I've tried to be as close to the Google Translate example given for Cloud Functions. However, I get the following error when the Cloud Function is invoked.
RequestError: Error: getaddrinfo ENOTFOUND script.google.com
script.google.com:443
Here is my Cloud Function code -
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const request = require('request-promise');
exports.makeUppercase =
functions.database.ref('/users/{userid}/logs/{logid}/mykey')
.onWrite(event => {
var url = `https://script.google.com/macros/s/.../exec`;
var retstr = request(url, {resolveWithFullResponse: true}).then(
response => {
if (response.statusCode === 200) {
const data = response.body;
return event.data.ref.parent.child('uppercase').set(data);
}
throw response.body;
});
});
Thanks in advance,
Regards
Rahul
I had the same issue and found this answer(https://stackoverflow.com/a/42775841).
Seems like calling Google Apps Script is considered external.
I have created Firebase Cloud Functions app,
I created function with https.onRequest.
and get data with req.body but there is not data there.
Can Firebase Cloud Functions can handle HTTP POST method?
This is my sample code:-
var functions = require('firebase-functions');
exports.testPost = functions.https.onRequest((req, res) => {
console.log(req.body);
});
I tested by postman with POST method but didn't show result in Firebase log.
Functions built on Firebase can also use Express.js routers for handling GET/POST/PUT/DELETE, etc... is fully supported by Google, and is the recommended way to implement these types of functions.
More documentation can be found here:
https://firebase.google.com/docs/functions/http-events
Here's a working example built on Node.js
const functions = require('firebase-functions');
const express = require('express');
const cors = require('cors');
const app = express();
// Automatically allow cross-origin requests
app.use(cors({ origin: true }));
app.get('/hello', (req, res) => {
res.end("Received GET request!");
});
app.post('/hello', (req, res) => {
res.end("Received POST request!");
});
// Expose Express API as a single Cloud Function:
exports.widgets = functions.https.onRequest(app);
Then, run firebase deploy, and that should compile your code and create the new "widgets" function. Note: You can rename widgets to anything you want. Ultimately, it will generate a URL for calling the function.
I am planning to do the same thing. What I reckon the approach should be is to check the request.method in the function body. A probable approach can be:
if (request.method != "POST") {
respond.status(400).send("I am not happy");
return;
}
// handle the post request
Here's some reference to the details regarding what the request object holds: https://firebase.google.com/docs/functions/http-events
Firebase functions support GET, POST, PUT, DELETE, and OPTIONS method, and you can check what kind of methods that trigger your function.
// Check for POST request
if(request.method !== "POST"){
res.status(400).send('Please send a POST request');
return;
}
Then to get data from POST request (for example JSON type) will be in the header of your request.
const postData = request.body;
// for instance
const format = req.body.format;
// query string params
let format = req.query.format;
Maybe your project hasn't been setup to communicate with your firebase database. Try the following from your terminal:
npm install -g firebase-tools
Then inside your project folder, run the following and login using your credentials
firebase login
Then
firebase init functions
This will create a folder with index.js, package.json and node_modules
If you are using Postman correctly the rest of your code should work.