Preflight error on Firebase cloud functions - javascript

I'm facing a preflight error when I try to call a cloud function of mine from my website. I implemented the cors module in my cloud function, and my request got the cors header authorizations
The cloud function :
const cors = require('cors')({ origin: true });
exports.CLOUDFUNCTION = functions.https.onRequest(
(request: any, response: any) => {
cors(request, response, async () => {
response.status(200).send('hello');
})
}
);
The website request :
fetch('FIREBASE_URL/CLOUDFUNCTION',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Headers': 'Authorization'
},
body: JSON.stringify(body), // body is a simple {"variable": "value"}
}
);
The error
Access to fetch at 'FIREBASE_URL/CLOUDFUNCTION' from origin 'MYWEBSITE' 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.

If you are getting a 403 Forbidden Error when trying to access your function via it's URL, you have a problem with your function's deployment, it's configuration or you have made a mistake in the URL.
Note: While I use "traditional" require statements here to match your example, I encourage you to use newer ES6+ JavaScript features (const, let, async/await, import, etc.) for any newly written functions.
Deploy using the latest firebase-tools version
Make sure you are deploying using the latest version of the firebase-tools CLI.
When v7.7.0 of firebase-tools released (Jan 15, 2020), the way Cloud Functions are invoked on the server changed so that functions could be invoked by only authenticated users. To be accessible to Firebase Users, these functions must be made public by explicitly granting the allUsers group the Cloud Function Invoker permission.
In v7.7.0 and later, this is done for you as part of deployment. However, if you deploy functions using an older version, you will need to configure this permission yourself or redeploy using a newer firebase-tools version.
Check the exported function name
Make sure the function you export is named what you expect once deployed.
In particular, pay close attention to when your function is exported as part of a function group either deliberately or accidentally. This often turns up when you've split your functions into multiple files. In the below code blocks, CLOUDFUNCTION gets exported as myFunctions-CLOUDFUNCTION and not just CLOUDFUNCTION as you may expect.
// myFunctions.js
exports.CLOUDFUNCTION = functions.https.onRequest(...);
// index.js (incorrect)
exports.myFunctions = require("./myFunctions.js");
// index.js (correct)
const myFunctions = require("./myFunctions.js");
exports.CLOUDFUNCTION = myFunctions.CLOUDFUNCTION;
Check the function's URL
Check the Cloud Functions URL you are using for typos. Function names in Cloud Functions URLs are case-sensitive.
The correct URL should follow the format:
https://<REGION>-<PROJECT_ID>.cloudfunctions.net/<EXPORTED_FUNCTION_NAME>
Example:
https://us-central1-fir-sandbox.cloudfunctions.net/echo
Handle CORS errors & stop processing
In your code example, you pass in the NextFunction without an error handler. While using { origin: true }, this is "fine", but you'll start running into trouble when you start restricting the origins you call your function from. This is particularly handy for preventing your functions being invoked directly by their URL (where origin would be undefined). Take a look at the documentation or the next section for more info.
const cors = require('cors')({ origin: true });
exports.CLOUDFUNCTION = functions.https.onRequest(
(request, response) => { // <-- don't use `: any` here, as you are disabling the built-in types provided by firebase-functions
cors(request, response, async (err) => {
if (err) {
// Denied by CORS/error with CORS configuration
console.error("CORS blocked request -> ", err);
response.status(403).send("Forbidden by CORS");
return;
}
response.status(200).send('hello');
})
}
);
Optional: Tighten the cors configuration
While you can reflect the Access-Control-* headers using the cors package, consider explicitly setting these server-side.
const { projectId: PROJECT_ID } = JSON.parse(process.env.FIREBASE_CONFIG);
const cors = require('cors')({
// during emulation, allow localhost & calling directly (i.e. no origin specified);
// at all other times, restrict to deployed hosting sites only
origin: process.env.FUNCTIONS_EMULATOR === "true"
? /^(https?:\/\/localhost:\d+|undefined)$/
: [`https://${PROJECT_ID}.firebaseapp.com`, `https://${PROJECT_ID}.web.app`],
allowedHeaders: ['Content-Type', 'Authorization']
});
exports.CLOUDFUNCTION = functions.https.onRequest(
(request, response) => {
cors(request, response, async (err) => {
if (err) {
// Denied by CORS/error with CORS configuration
console.error("CORS blocked request -> ", err);
response.status(403).send("Forbidden by CORS");
return;
}
response.status(200).send('hello');
})
}
);
This simplifies your client-side code:
fetch('FIREBASE_URL/CLOUDFUNCTION',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
}
);
Optional: Use Callable Functions
If your functions will require you to do actions on behalf of a user, you could make use of Callable Cloud Functions instead of the more bare-bones HTTPS Request functions. This version of a HTTPS Function handles CORS, authentication, and supports Promise-based returning of data.
Note: This will still require the function to be public as described above.
On the server side:
exports.CLOUDFUNCTION = functions.https.onCall(async (data, context) => {
if (!context.auth) {
// users must be logged in
throw new functions.https.HttpsError(
'failed-precondition',
'The function must be called while authenticated.'
);
}
if (data.variable === undefined)) {
throw new functions.https.HttpsError(
'invalid-argument',
'Parameter "variable" must be a string'
);
}
// you can return a promise here
// this sends back the JSON string "hello world"
return "hello world";
});
On the client side:
const callFunction = firebase.functions().httpsCallable('CLOUDFUNCTION');
callFunction(body)
.then(
(responseData) => {
// TODO: handle response
},
(functionError) => {
// TODO: handle error
}
);

Related

Firebase 'internal' error when using Functions and Admin

I am having trouble with some functions that have been working previously. I have created a function to let the user create another user and it was working fine. Functions that do not use Admin works fine just as before.
However, due to some Firebase updates, the function broke and I am getting an 'internal' error. I had to change import firebase from "firebase/app"; to import firebase from "firebase/compat/app"; as well as import "firebase/compat/functions"; but that did not work, as well as updating firebase to "^9.8.1", but that did not work either.
Here is my web function:
async registerUser(userInfo) {
const functions = getFunctions();
const createUser = httpsCallable(functions, "createUser");
// Used to have this:
// let createUser = firebase.functions().httpsCallable("createUser");
//Call to function where it breaks.
return await createUser({
//User data here
})
.then(
//stuff happens here
).catch((error) => {
//Error happens here
})
}
Here is the function that was already deployed in Firebase:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.createUser = functions.https.onCall(async (userData) => {
return await admin
.auth()
.createUser(userData)
.then(() => {
return { isError: false };
})
.catch((error) => {
return { isError: true, errorMessage: error };
});
});
Here is the response log:
Request Method: OPTIONS
Status Code: 403
Referrer Policy: strict-origin-when-cross-origin
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
content-length: 305
content-type: text/html; charset=UTF-8
date: Tue, 24 May 2022 16:04:14 GMT
server: Google Frontend
You can refer to the Admin SDK error handling page and check the Structure of the error, the refer to policy: strict-origin-when-cross-origin part gives us a good starting point.
But first, we can see the root cause of this issue as in the same page we have a table for Platform error codes where:
INTERNAL | Internal server error. Typically a server bug.
In the Firebase Admin Authentication API Errors we have a similar table where:
auth/internal-error | The Authentication server encountered an unexpected error while trying to process the request. The error message should contain the response from the Authentication server containing additional information. If the error persists, please report the problem to our Bug Report support channel.
Now talking about the cors message, this question suggests:
Consider importing like this, as shown in the samples:
const cors = require('cors')({origin: true});
And the general form of your function will be like this:
exports.fn = functions.https.onRequest((req, res) => {
cors(req, res, () => {
// your function body here - use the provided req and res from cors
})
});
You might need to make some changes to the structure as the question has some time, so I will also leave the reference to the Call functions via HTTP requests and check if it works for you.
I will follow up if you provide updates and consider submitting a bug report as previously mentioned by the documentation if this is necessary.

Cors is not working for two different origins

I have two servers, frontend (Next.js) and backend (express.js api server).
Frontend server is running without any additions. But I have an nginx proxy for backend.
So far everything is good because they are not connected yet.
Frontend: is working as it should be.
Backend: I can make calls directly from the backend itself (by self origin).
When I make a fetch get call from my frontend server to the backend server, it normally gives a cors error because the origins are different.
For this, I set the backend server with cors:
// /src/middlewares/cors.ts
import cors from 'cors';
const whitelist = new Set(['http://192.168.1.106:3000', 'https://192.168.148.132']);
// frontend: http://192.168.1.106:3000
// backend: https://192.168.148.132
const corsOptions = {
optionsSuccessStatus: 200,
origin: (origin: any, callback: any) => {
console.log('origin: ' + origin);
if (whitelist.has(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
// credentials: true,
};
export default cors(corsOptions);
and
// /app.ts
import cors from './middlewares/system/cors.js';
.
.
// setup cors
app.options('*', cors);
app.use(cors);
.
.
After doing this, I reach my main goal. The frontend server can make call to the backend server.
output:
But this time I notice a problem. I can't send self request to backend anymore (by self origin).
When dealing with this I looked at the origins that came to the /src/middlewares/cors.ts file that I showed above.
for frontend:
for backend:
I am using self signed ssl in nginx for back server.
And there is not any cors relevant headers in conf.
How can i solve this situation?
(If I'm missing something, you can point it out in the comments.)
The Origin header is only set in cross-origin requests. If you call your backend directly, the Javascript value is undefined, and in this case you must not restrict anything. You could, for example, write
if (!origin || whitelist.has(origin)) {
callback(null, true);
}

Request from Firebase Hosting to Firebase Function blocked by CORS

I'm trying to send push notifications between two devices for a tiny prototype. Both of them are Vue.js apps with firebase SDK integrated, so to implement a push notification flow I deployed a firebase function, but when I call it from any of devices, a CORS error is received as a response.
Both devices (mobile and desktop) have the same client code and knows the token of each other (storage into a firebase real-time database).
The function only uses firebase messaging to send the push notification.
Firebase function:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const cors = require('cors')({ origin: true });
admin.initializeApp();
exports.notification = functions.https.onRequest((req, res) => {
return cors(req, res, () => {
if (req.method === "POST") {
return admin.messaging().send(notification)
.then(result => {
console.log(result);
res.status(200).send("ok")
})
.catch(err => res.status(500).send(err));
} else {
return res.status(400).send("Method not allowed");
}
});
});
Client code:
send(notification, token) {
return fetch("https://[zone]-[project].cloudfunctions.net/notifications", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token, notification })
});
}
And the error is:
Access to fetch at 'https://[zone]-[project].cloudfunctions.net/notifications' from origin 'https://[project].web.app' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
Could you use The functions.https.onCall trigger?
See https://firebase.google.com/docs/functions/callable .
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, and then add client logic to call the function from your app.
The URI that I used to invoke the function was wrong. It's solved. Sorry about that question.

Aftership Api with React fetch issue

I added aftership in my react app the following way:
const Aftership = require('aftership')('put-my-API-KEY', {
endpoint: 'https://api.aftership.com/v4'
});
let query = {
page:10,
limit:5
};
Aftership.call('GET', '/trackings', {
query: query
}, (err, result) => {
console.log(err);
console.log(result);
});
export default Aftership;
When I am using node src/aftership.js in terminal, then fetching data works well (after comment out last line export default Aftership).
But when I fetch from src/containers/Tracking.js file the following way:
import Aftership from '../../aftership';
...
componentDidMount (){
let query = {
page:10,
limit:5
};
Aftership.call('GET', '/trackings', {
query: query
}, (err, result) => {
console.log(err);
console.log(result);
});
}
it's showing me an error in console:
Failed to load https://api.aftership.com/v4/trackings?page=10&limit=5:
Request header field x-aftership-agent is not allowed by
Access-Control-Allow-Headers in preflight response. Tracking.js:28
TypeError: Failed to fetch Tracking.js:28 Undefined
Can anyone help me what is my issue and what should I do know?
This looks like a Cross-Origin Resource Sharing (CORS) problem. To simply put this is happening you are using your local development host with third party instead. To avoid such errors, you can use Chrome extensions like https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi. This extension will edit response header to Access-Control-Allow-Headers: '*', which allows all headers on request body.
This is not recommended for daily use, so I recommend to add wildcard for only APIs you would like to use. In this case add https://api.aftership.com/* to extension settings

Enabling CORS in Cloud Functions for Firebase

I'm currently learning how to use new Cloud Functions for Firebase and the problem I'm having is that I can't access the function I wrote through an AJAX request. I get the "No 'Access-Control-Allow-Origin'" error. Here's an example of the function I wrote:
exports.test = functions.https.onRequest((request, response) => {
response.status(500).send({test: 'Testing functions'});
})
The function sits in this url:
https://us-central1-fba-shipper-140ae.cloudfunctions.net/test
Firebase docs suggests to add CORS middleware inside the function, I've tried it but it's not working for me: https://firebase.google.com/docs/functions/http-events
This is how I did it:
var cors = require('cors');
exports.test = functions.https.onRequest((request, response) => {
cors(request, response, () => {
response.status(500).send({test: 'Testing functions'});
})
})
What am I doing wrong? I would appreciate any help with this.
UPDATE:
Doug Stevenson's answer helped. Adding ({origin: true}) fixed the issue, I also had to change response.status(500) to response.status(200) which I completely missed at first.
There are two sample functions provided by the Firebase team that demonstrate the use of CORS:
Time server with date formatting
HTTPS endpoint requiring Authentication
The second sample uses a different way of working with cors than you're currently using.
Consider importing like this, as shown in the samples:
const cors = require('cors')({origin: true});
And the general form of your function will be like this:
exports.fn = functions.https.onRequest((req, res) => {
cors(req, res, () => {
// your function body here - use the provided req and res from cors
})
});
You can set the CORS in the cloud function like this
response.set('Access-Control-Allow-Origin', '*');
No need to import the cors package
For anyone trying to do this in Typescript this is the code:
import * as cors from 'cors';
const corsHandler = cors({origin: true});
export const exampleFunction= functions.https.onRequest(async (request, response) => {
corsHandler(request, response, () => {
//Your code here
});
});
One additional piece of info, just for the sake of those googling this after some time:
If you are using firebase hosting, you can also set up rewrites, so that for example a url like (firebase_hosting_host)/api/myfunction redirects to the (firebase_cloudfunctions_host)/doStuff function. That way, since the redirection is transparent and server-side, you don't have to deal with cors.
You can set that up with a rewrites section in firebase.json:
"rewrites": [
{ "source": "/api/myFunction", "function": "doStuff" }
]
No CORS solutions worked for me... till now!
Not sure if anyone else ran into the same issue I did, but I set up CORS like 5 different ways from examples I found and nothing seemed to work. I set up a minimal example with Plunker to see if it was really a bug, but the example ran beautifully. I decided to check the firebase functions logs (found in the firebase console) to see if that could tell me anything. I had a couple errors in my node server code, not CORS related, that when I debugged released me of my CORS error message. I don't know why code errors unrelated to CORS returns a CORS error response, but it led me down the wrong rabbit hole for a good number of hours...
tl;dr - check your firebase function logs if no CORS solutions work and debug any errros you have
Updated answer: using cors library with Typescript support:
install cors
npm i -S cors
npm i --save-dev #types/cors
index.ts:
import * as cors from "cors";
const corsHandler = cors({ origin: true });
// allow cors in http function
export const myFunction = functions.https.onRequest((req, res) => {
corsHandler(req, res, async () => {
// your method body
});
});
Old answer:
(not working anymore)
Found a way to enable cors without importing any 'cors' library. It also works with Typescript and tested it in chrome version 81.0.
exports.createOrder = functions.https.onRequest((req, res) => {
// browsers like chrome need these headers to be present in response if the api is called from other than its base domain
res.set("Access-Control-Allow-Origin", "*"); // you can also whitelist a specific domain like "http://127.0.0.1:4000"
res.set("Access-Control-Allow-Headers", "Content-Type");
// your code starts here
//send response
res.status(200).send();
});
I have a little addition to #Andreys answer to his own question.
It seems that you do not have to call the callback in the cors(req, res, cb) function, so you can just call the cors module at the top of your function, without embedding all your code in the callback. This is much quicker if you want to implement cors afterwards.
exports.exampleFunction = functions.https.onRequest((request, response) => {
cors(request, response, () => {});
return response.send("Hello from Firebase!");
});
Do not forget to init cors as mentioned in the opening post:
const cors = require('cors')({origin: true});
Update: Any response function that takes time risk a CORS error with this implementation because this doesn't have the appropriate async/await. Don't use outside of quick prototyping endpoints that return static data.
This might be helpful.
I created firebase HTTP cloud function with express(custom URL)
const express = require('express');
const bodyParser = require('body-parser');
const cors = require("cors");
const app = express();
const main = express();
app.post('/endpoint', (req, res) => {
// code here
})
app.use(cors({ origin: true }));
main.use(cors({ origin: true }));
main.use('/api/v1', app);
main.use(bodyParser.json());
main.use(bodyParser.urlencoded({ extended: false }));
module.exports.functionName = functions.https.onRequest(main);
Please make sure you added rewrite sections
"rewrites": [
{
"source": "/api/v1/**",
"function": "functionName"
}
]
Simple solution using the Google Cloud Console Dashboard:
Go to your GCP console dashboard:
https://console.cloud.google.com/home/dashboard
Go to menu
"Cloud Functions" ("Compute" section)
Select your cloud function, e.g. "MyFunction", a side menu should appear on the right showing you the access control settings for it
Click on "Add Member", type in "allUsers" and select the role "Cloud Function Invoker"
Save it -> now, you should see a remark "Allow unauthenticated" in the list of your cloud functions
Access is now available to everybody from the internet with the correct config to your GCP or Firebase project. (Be careful)
If you don't/can't use cors plugin, calling the setCorsHeaders() function first thing in the handler function will also work.
Also use the respondSuccess/Error functions when replying back.
const ALLOWED_ORIGINS = ["http://localhost:9090", "https://sub.example.com", "https://example.com"]
// Set CORS headers for preflight requests
function setCorsHeaders (req, res) {
var originUrl = "http://localhost:9090"
if(ALLOWED_ORIGINS.includes(req.headers.origin)){
originUrl = req.headers.origin
}
res.set('Access-Control-Allow-Origin', originUrl);
res.set('Access-Control-Allow-Credentials', 'true');
if (req.method === 'OPTIONS') {
// Send response to OPTIONS requests
res.set('Access-Control-Allow-Methods', 'GET,POST','PUT','DELETE');
res.set('Access-Control-Allow-Headers', 'Bearer, Content-Type');
res.set('Access-Control-Max-Age', '3600');
res.status(204).send('');
}
}
function respondError (message, error, code, res) {
var response = {
message: message,
error: error
}
res.status(code).end(JSON.stringify(response));
}
function respondSuccess (result, res) {
var response = {
message: "OK",
result: result
}
res.status(200).end(JSON.stringify(response));
}
If there are people like me out there: If you want to call the cloud function from the same project as the cloud function it self, you can init the firebase sdk and use onCall method. It will handle everything for you:
exports.newRequest = functions.https.onCall((data, context) => {
console.log(`This is the received data: ${data}.`);
return data;
})
Call this function like this:
// Init the firebase SDK first
const functions = firebase.functions();
const addMessage = functions.httpsCallable(`newRequest`);
Firebase docs: https://firebase.google.com/docs/functions/callable
If you can't init the SDK here is the essence from the other suggestions:
If you use firebase hosting and host in the default location, choose rewrites: https://firebase.google.com/docs/hosting/full-config#rewrites
Or use CORS like krishnazden suggested: https://stackoverflow.com/a/53845986/1293220
A cors error can occur if you don't catch an error in a function. My suggestion is to implement a try catch in your corsHandler
const corsHandler = (request, response, handler) => {
cors({ origin: true })(request, response, async () => {
try {
await handler();
}
catch (e) {
functions.logger.error('Error: ' + e);
response.statusCode = 500;
response.send({
'status': 'ERROR' //Optional: customize your error message here
});
}
});
};
Usage:
exports.helloWorld = functions.https.onRequest((request, response) => {
corsHandler(request, response, () => {
functions.logger.info("Hello logs!");
response.send({
"data": "Hello from Firebase!"
});
});
});
Thanks to stackoverflow users: Hoang Trinh, Yayo Arellano and Doug Stevenson
Only this way works for me as i have authorization in my request:
exports.hello = functions.https.onRequest((request, response) => {
response.set('Access-Control-Allow-Origin', '*');
response.set('Access-Control-Allow-Credentials', 'true'); // vital
if (request.method === 'OPTIONS') {
// Send response to OPTIONS requests
response.set('Access-Control-Allow-Methods', 'GET');
response.set('Access-Control-Allow-Headers', 'Content-Type');
response.set('Access-Control-Max-Age', '3600');
response.status(204).send('');
} else {
const params = request.body;
const html = 'some html';
response.send(html)
} )};
Changing true by "*" did the trick for me, so this is how it looks like:
const cors = require('cors')({ origin: "*" })
I tried this approach because in general, this is how this response header is set:
'Access-Control-Allow-Origin', '*'
Be aware that this will allow any domain to call your endpoints therefore it's NOT secure.
Additionally, you can read more on the docs:
https://github.com/expressjs/cors
Cloud Functions for Firebase v2
Cloud Functions for Firebase v2 now allow you to configure cors directly in the HTTP options. It works without the need for any 3rd party package:
import { https } from 'firebase-functions/v2';
export myfunction = https.onRequest({ cors: true }, async (req, res) => {
// this will be invoked for any request, regardless of its origin
});
Beware:
At the time of writing, v2is in public preview.
Only a sub-set of regions is currently supported in v2.
Function names are restricted to lowercase letters, numbers, and dashes.
You can use v1 and v2 functions side-by-side in a single codebase. For improved readability, update your imports to access firebase-functions/v1 or firebase-functions/v2 respectively.
I have just published a little piece on that:
https://mhaligowski.github.io/blog/2017/03/10/cors-in-cloud-functions.html
Generally, you should use Express CORS package, which requires a little hacking around to meet the requirements in GCF/Firebase Functions.
Hope that helps!
For what it's worth I was having the same issue when passing app into onRequest. I realized the issue was a trailing slash on the request url for the firebase function. Express was looking for '/' but I didn't have the trailing slash on the function [project-id].cloudfunctions.net/[function-name]. The CORS error was a false negative. When I added the trailing slash, I got the response I was expecting.
If You are not using Express or simply want to use CORS. The following code will help resolve
const cors = require('cors')({ origin: true, });
exports.yourfunction = functions.https.onRequest((request, response) => {
return cors(request, response, () => {
// *Your code*
});
});
Go into your Google Cloud Functions. You may have not seen this platform before, but it's how you'll fix this Firebase problem.
Find the Firebase function you're searching for and click on the name. If this page is blank, you may need to search for Cloud Functions and select the page from the results.
Find your function, click on the name.
Go to the permissions tab. Click Add (to add user).
Under new principles, type 'allUsers' -- it should autocomplete before you finish typing.
Under select a role, search for Cloud Functions, then choose Invoker.
Save.
Wait a couple minutes.
This should fix it. If it doesn't, do this AND add a CORS solution to your function code, something like:
exports.sendMail = functions.https.onRequest((request, response) => {
response.set("Access-Control-Allow-Origin", "*");
response.send("Hello from Firebase!");
});
If you're testing firebase app locally then you need to point functions to localhost instead of cloud. By default, firebase serve or firebase emulators:start points the functions to server instead of localhost when you use it on your web app.
Add below script in html head after firebase init script:
<script>
firebase.functions().useFunctionsEmulator('http://localhost:5001')
</script>
Make sure to remove this snippet when deploying code to server.
I got the error because I was calling a function that didn't exist on the client side. For example:
firebase.functions().httpsCallable('makeSureThisStringIsCorrect');
Adding my piece of experience.
I spent hours trying to find why I had CORS error.
It happens that I've renamed my cloud function (the very first I was trying after a big upgrade).
So when my firebase app was calling the cloud function with an incorrect name, it should have thrown a 404 error, not a CORS error.
Fixing the cloud function name in my firebase app fixed the issue.
I've filled a bug report about this here
https://firebase.google.com/support/troubleshooter/report/bugs
From so much searching, I could find this solution in the same firebase documentation, just implement the cors in the path:
import * as express from "express";
import * as cors from "cors";
const api = express();
api.use(cors({ origin: true }));
api.get("/url", function);
Link firebase doc: https://firebase.google.com/docs/functions/http-events
If you prefer to make a single handler function (reference answer)
const applyMiddleware = handler => (req, res) => {
return cors(req, res, () => {
return handler(req, res)
})
}
exports.handler = functions.https.onRequest(applyMiddleware(handler))
I'm a very beginner with Firebase (signed up 30 minutes ago). My issue is that I called my endpoint
https://xxxx-default-rtdb.firebaseio.com/myendpoint
Instead of
https://xxxx-default-rtdb.firebaseio.com/myendpoint.json
If you just started with Firebase, make sure you don't forget the .json extension.
I have been trying this for a long time.
It finally finally worked when I made this change.
app.get('/create-customer', (req, res) => {
return cors()(req, res, () => {
... your code ...
The Big difference is that I used cors()(req, res... instead of directly cors(req, res...
It Now works perfectly.
With the same access allow control origin error in the devtool console, I found other solutions with also more modern syntax :
My CORS problem was with Storage (and not RTDB neither the browser...), and then I'm not in possession of a credit card (as requested by the aforementioned solutions), my no-credit card solution was to :
install gsutil :
https://cloud.google.com/storage/docs/gsutil_install#linux-and-macos
to create a cors.json file to be loaded via terminal with gsutil
gsutil cors set cors.json gs://[ your-bucket ]/-1.appspot.com
https://firebase.google.com/docs/storage/web/download-files#cors_configuration
In my case the error was caused by cloud function invoker limit access. Please add allUsers to cloud function invoker. Please catch link. Please refer to article for more info
If none of the other solutions work, you could try adding the below address at the beginning of the call to enable CORS - redirect:
https://cors-anywhere.herokuapp.com/
Sample code with JQuery AJAX request:
$.ajax({
url: 'https://cors-anywhere.herokuapp.com/https://fir-agilan.web.app/gmail?mail=asd#gmail.com,
type: 'GET'
});
See below for how I set up my Express with CORS.
The 'https://pericope.app' is my custom domain for my Firebase project.
It looks like all other answers recommend origin:true or *.
I'm hesitant to allow all origins since it would allow anyone else access to the api. That's fine if you are creating a public service, but if you're doing anything with your data it is risky since it is a privileged environment. For example, this admin SDK bypasses any security rules you have setup for Firestore or Storage.
//Express
const express = require('express');
const app = express();
const cors = require('cors');
app.use(cors({
origin: 'https://pericope.app'
}));

Categories

Resources