266

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.

GabLeRoux
  • 16,715
  • 16
  • 63
  • 81
Andrey Pokrovskiy
  • 2,756
  • 2
  • 13
  • 10
  • Also a sample in the docs [here](https://firebase.google.com/docs/hosting/url-redirects-rewrites#section-headers) – Kato Apr 24 '17 at 21:12
  • I have some functions that work with the solution provided but now am trying a new function which essentially adds open graphs to the top of my index.html and returns the updated index.html and I can't get it to work :( keep getting the ACCESS-CONTROL--- error – TheBen Apr 26 '18 at 22:59
  • 2
    wrapping the incoming request in cors() like above was the only thing that worked for me – Charles Harring Apr 19 '20 at 01:34
  • can you edit your "update" to underline that the cors middleware is required? This will save some people some time – Antoine Weber Jul 16 '20 at 15:36
  • In 2023, [the relevant docs are here](https://firebase.google.com/docs/functions/callable?gen=2nd#cors) – Ben Aug 28 '23 at 04:12

34 Answers34

265

There are two sample functions provided by the Firebase team that demonstrate the use of CORS:

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
    })
});
thdoan
  • 18,421
  • 1
  • 62
  • 57
Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • 5
    It looks like this is where the whitelist of domains to allow access is defined? And setting `origin: true` allows any domain to access? (https://www.npmjs.com/package/cors) @Doug Stevenson Do you think firebase could write up a doc on the basics needed for client/server https functions? The samples repo is good, but we had missed this extra bit of require. – Alan Aug 25 '17 at 09:40
  • 27
    To anyone willing to add CORS support to their back-ends: please make sure you understand the consequences and how to properly configure it. "origin: true" is cool for testing but it defeats the whole purpose :) – dSebastien Apr 17 '18 at 19:30
  • @dSebastien, could you give an example of cors with specific origin which I assume that's what you mean it should be used? I have problem getting it to work – TheBen Apr 26 '18 at 23:01
  • Hey Doug, I've posted a question on Firebase, it's been awhile with no answer and am kind of desperate for it otherwise wouldn't bug you here. Appreciate any comment/reply. https://stackoverflow.com/q/50053798/5601401 – TheBen May 10 '18 at 15:07
  • 2
    google cloud functions do not allow the wildcard origin: https://cloud.google.com/functions/docs/writing/http#authentication_and_cors – Corey Cole Sep 19 '19 at 21:00
  • 1
    Just a reminder for everyone still importing cors like Doug brilliantly mentioned, don't forget to wrap the response like Andrey did, otherwise it won't work! – Gustavo Garcia Apr 21 '20 at 19:24
  • TypeError: 'origin' is undefined. – Antonio Ooi May 06 '20 at 10:20
  • 2
    As others have mentioned, can you update your answer to point out that cors middleware is indeed required? If we skim through your answer, we think that the only step needed is to write `const cors = require('cors')({origin: true});`, but it's not the case – Antoine Weber Jul 16 '20 at 15:37
  • response.set('Access-Control-Allow-Origin', '*'); this works fine for me. Do check this solution by @deanwilliammills – Alok Prusty Sep 23 '20 at 13:21
  • Doug, you forgot the `return` keyword in your snippet. It should be: `return cors(req, res, () => {..` instead. – Antoine Weber Oct 05 '20 at 01:05
  • @AntoineWeber So, what happens if you don't add it? HTTP functions don't require a return value. They just require a response be sent via the `res` parameter. – Doug Stevenson Oct 05 '20 at 01:10
  • Ok it works without the `return`. But the sample function uses `return` for some reason. I guess I got confused by that inconsistency – Antoine Weber Oct 05 '20 at 01:20
  • 1
    @AntoineWeber Yes, I know the author of those samples, and I disagreed with him over the use of unnecessary and misleading returns throughout, but nothing changed. ¯\\_(ツ)_/¯ – Doug Stevenson Oct 05 '20 at 01:27
  • 1
    ANd how would this same problem be solved for "onCall" Cloud functions? Because these functions are not quite like express endpoints and I don't have to define middleware supposedly – perepm Oct 23 '20 at 06:39
  • I needed to `npm i cors` and `@types/cors` for this work. Thank you! – Cooper Scott Dec 08 '20 at 18:14
  • will this works for onCall too? – Richmond Mar 24 '22 at 06:01
  • @AntoineWeber does this approach work on a per-router basis as well? – Todd Rylaarsdam May 03 '22 at 23:26
  • finally, a working solution – Saif Ur Rehman Saif May 02 '23 at 18:45
148

You can set the CORS in the cloud function like this

response.set('Access-Control-Allow-Origin', '*');

No need to import the cors package

GabLeRoux
  • 16,715
  • 16
  • 63
  • 81
deanwilliammills
  • 2,617
  • 2
  • 21
  • 27
88

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
           });
           
    });
Lasharela
  • 1,307
  • 1
  • 11
  • 23
Yayo Arellano
  • 3,575
  • 23
  • 28
  • 8
    Solution will make you lose logging on cloud functions (very bad) and proper async / await functionality, you risk the function content being prematurely ended inside the callback on long calls. – Oliver Dixon Dec 16 '18 at 21:30
  • 2
    google cloud functions do not allow the wildcard origin: https://cloud.google.com/functions/docs/writing/http#authentication_and_cors – Corey Cole Sep 19 '19 at 21:00
  • 6
    @YayoArellano , thanks. Your answer helped me, however I made a slight change: `corsHandler(request, response, () => { YOUR CODE HERE });` – CloudWindMoonSun Dec 17 '20 at 11:53
  • 2
    @OliverDixon do you have a better solution that does not have the downside of possibly risking the function content to being prematurely ended during long calls? Probably wrapping it in a Promise that only resolves once the callback "completed"? – sceee May 06 '21 at 11:59
  • @OliverDixon Can you explain "you risk the function content being prematurely ended inside the callback on long calls." please? – 1252748 Jan 10 '22 at 05:58
  • lose logging on cloud functions v it doesn't work === prefer the former – danday74 Jan 12 '22 at 17:13
  • @OliverDixon Why will the function content be prematurely ended inside the callback? – rbansal Jan 31 '23 at 04:53
54

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" }
]
GabLeRoux
  • 16,715
  • 16
  • 63
  • 81
Pablo Urquiza
  • 726
  • 7
  • 10
  • 3
    imo, this is the best answer, since it solves the actual problem without adding any additional security problems. This way the cloud functions are served from the same domain as the rest and you dont even need any cors. – koljaTM Feb 03 '19 at 15:29
  • 6
    This is a great feature indeed, but it currently only works if the functions live in the default region (us-central1). I wanted to deploy my functions to europe-west1 for latency reasons and ran into this issue: https://github.com/firebase/firebase-tools/issues/842 – Alex Suzuki Jun 26 '19 at 14:21
  • 1
    The redirect works fine and makes the URL cleaner, but I haven't figured out how to pass GET parameters. The function (after rewrite) seems to be called without parameters. – royappa Jul 23 '19 at 13:57
  • 1
    using firebase Hosting? if yes, then your cloud function MUST be in "us-central1" region, this is still true in june 2021. – WebDev-SysAdmin Jun 20 '21 at 19:14
  • 1
    Here's the link to the docs if anyone is curious: https://firebase.google.com/docs/hosting/full-config#rewrite-functions – phreakhead Sep 01 '21 at 18:17
  • 3
    Is there any way to use this rewrite with the httpCallable? Or do we need to resort to normal web functions at that point? – phreakhead Sep 01 '21 at 18:56
  • This didn't work for me and doesn't make sense. The documentation says, "Use a rewrite to show the same content for multiple URLs." The example is to redirect 404 requests to index.html. The documentation shows how to put "Access-Control-Allow-Origin" in the headers, which didn't work either. I'll ask a new question. – Thomas David Kehoe Feb 10 '23 at 20:44
38

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

tbone849
  • 925
  • 8
  • 18
  • 3
    this drove me crazy. in my case it wasn't even error in code! it was ```Error: quota exceeded (Quota exceeded for quota group 'NetworkIngressNonbillable' and limit 'CLIENT_PROJECT-1d' of service 'cloudfunctions.googleapis.com ``` so basically free quota was exceeded and functions returned cors error – Stanislau Buzunko Oct 17 '19 at 19:16
  • 1
    Happend a couple of times here, same error is returned from the server aswell as cors: Error: internal is basically the error. This error will also happen if you run the wrong function, for example mistyping a function name – Henrik Bøgelund Lavstsen May 13 '20 at 02:13
  • When you try to request for Google reCAPTCHA verification within cloud function, the browser throws you the CORS error too. When I check the Firebase Console function log, it says `access to external network resources not allowed if the billing account is not enabled`. After enabling the billing account, it works perfectly. This is also one of the non-cors related examples but a cors error is thrown. – Antonio Ooi May 27 '20 at 09:52
  • In my case, the issue was that I wasn't logged in under the correct Firebase project (`firebase use ` on the command-line) before running the emulator. – Jaromír Adamec Feb 04 '21 at 19:24
  • Same scenario here, very misleading cors error – conor909 Oct 31 '22 at 19:05
24

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();
});
GabLeRoux
  • 16,715
  • 16
  • 63
  • 81
GorvGoyl
  • 42,508
  • 29
  • 229
  • 225
  • This worked for me adding `res.set("Access-Control-Allow-Origin", "*")`; only did not work `res.set("Access-Control-Allow-Headers", "Content-Type");` solved my issue – Amina Darwish Aug 27 '20 at 07:24
  • 2
    This did not work for me, because it didn't support the OPTIONS method "preflight check" before the GET/POST request. I had to switch to the `cors` package (or recreate the `OPTIONS` special response, which ended up being more trouble than it's worth) – zeroasterisk Sep 29 '20 at 04:22
22

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.

GabLeRoux
  • 16,715
  • 16
  • 63
  • 81
Jaap Weijland
  • 3,146
  • 5
  • 23
  • 31
  • 2
    this worked when other SO answers with setting the headers manually did not – Jim Factor May 28 '18 at 21:48
  • This works but it can cause TSlint error if you had it enabled and you cannot deploy to firebase. Put the response inside the cors closure to overcome it `cors(request, response, () => { return response.send("Hello from Firebase!"); });` – Spiral Out Sep 15 '18 at 15:01
  • 2
    2 errors here guys. First one. Anything after the cors function will run twice (since the first request is preflight). Not good. Second, @SpiralOut your solution will make you lose logging on cloud functions (very bad) and proper async / await functionality, you risk the function content being prematurely ended inside the callback. – Oliver Dixon Dec 16 '18 at 20:53
  • @SpiralOut you can simply disable tslint – Vlad Mar 17 '19 at 05:06
  • 2
    Having learned a lot about gcf in the last year, I wouldn’t recommend this answer anymore. It could be handy for quick prototypes, but avoid this in real production cases – Jaap Weijland Mar 17 '19 at 16:37
  • @SpiralOut i mean remove tslint command from firebase build script only – Vlad Mar 22 '19 at 18:58
  • 2
    @JaapWeijland please update your answer with any info why this approach is bad for production code. As eventually all (seemingly working) examples from stackoverflow sooner or later end up in production... – Simon B. Aug 11 '20 at 11:48
15

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"
      }
]
Sandy
  • 505
  • 4
  • 15
  • 4
    To anyone reading this considering putting express inside their cloud function - just don't. Spinning up express takes up extra resources, etc, and you already have all that functionality implemented. Firebase functions !== node. – David May 14 '21 at 06:43
  • 2
    It may literally spin up a new express server *per request*. I'm really not sure why they have this stuff in the official docs. – David May 14 '21 at 06:49
  • One downside of this is that the streaming is not working in this case. – Shajeel Afzal Apr 21 '23 at 13:31
14

Simple solution using the Google Cloud Console Dashboard:

  1. Go to your GCP console dashboard:

https://console.cloud.google.com/home/dashboard

  1. Go to menu

"Cloud Functions" ("Compute" section)

  1. Select your cloud function, e.g. "MyFunction", a side menu should appear on the right showing you the access control settings for it

  2. Click on "Add Member", type in "allUsers" and select the role "Cloud Function Invoker"

  3. 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)

dimib
  • 716
  • 6
  • 9
  • That worked. The Google Cloud Console Dashboard has changed. Now you go to `Resources`, then `Cloud Functions`. From your list of Cloud Functions, click on the function, to the `PERMISSIONS` tab, click `GRANT ACCESS`, then under `Add principals` type in `allUsers`, then under `Assign roles` select `Cloud Functions` and then `Cloud Function Invoker` and then `SAVE`. This should work for development but I'm going to revoke this permission for production. – Thomas David Kehoe Feb 10 '23 at 18:51
10

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));
}
KasparTr
  • 2,328
  • 5
  • 26
  • 55
9

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.
Mobiletainment
  • 22,201
  • 9
  • 82
  • 98
  • 2
    This is not working for me. – rbansal Jan 31 '23 at 05:39
  • 1
    This was the only solution that worked for me; it allowed for the creation of a 'proxy server' on Firebase Functions for utilising Google's Places API on a web interface. – Quins Feb 08 '23 at 18:55
  • How do I allow only specific domains? – Malachi Bazar Jul 06 '23 at 12:12
  • @MalachiBazar: instead of setting `cors` to `true`, you can set it directly to the domain you want to allow. In addition to specifying a `string`, it even supports working with Regex or array of strings in case you want to handle multiple domains. – Mobiletainment Jul 06 '23 at 12:56
7

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:

zeekrey
  • 391
  • 6
  • 16
6

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

Rodrigo João Bertotti
  • 5,179
  • 2
  • 23
  • 34
  • Good answer but one nit: As far as the status code of the error, rather than a 500, I think that it’s probably better to response with a 403. That’s (roughly) what the spec recommends at https://fetch.spec.whatwg.org/#http-responses. And in general, IMHO, it seems not optimal to send a 500 from application code — because that’s gonna make it harder for you to distinguish cases of your application code throwing an intended error from cases of the server/runtime code hitting some other kind of internal failure (maybe even before it ever executes your application code). – sideshowbarker Dec 03 '20 at 16:44
  • 1
    Thanks for the comment :) The 500 response code is because is not an error related to cors, because of that I think is more appropriate to use a status code >= 500 rather than 403. What do you think? – Rodrigo João Bertotti Dec 03 '20 at 17:12
  • I have tried almost all answers on this page and this is the only one that worked. Thank you! – Craig Howell Sep 24 '21 at 13:33
  • I'm happy that worked! :) – Rodrigo João Bertotti Sep 24 '21 at 16:51
5

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)
} )};
Gleb Dolzikov
  • 776
  • 8
  • 13
  • google cloud functions do not allow the wildcard origin: https://cloud.google.com/functions/docs/writing/http#authentication_and_cors – Corey Cole Sep 19 '19 at 21:00
  • where do i put in my function body? I have posted my code here https://stackoverflow.com/questions/68646425/firebase-function-no-access-control-allow-origin-header-is-present-on-the-req – Jag99 Aug 04 '21 at 10:06
4

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

Rob
  • 2,243
  • 4
  • 29
  • 40
3

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!

mhaligowski
  • 2,182
  • 20
  • 26
  • 4
    Not sure what you mean by hacking ? Care to elaborate a bit? Read your post but I don't see you mentioning it – TheBen Apr 26 '18 at 23:03
  • 2
    author of the cors module here; by "hacking" mhaligowski simply meant that he had to wrap the call to the cors module to make it match the way Express calls middleware (i.e. supply a function as third parameter after req & res) – Troy Mar 19 '20 at 18:40
  • 3
    That link is broken https://mhaligowski.github.io/blog/2017/03/10/cors-in-cloud-functions.html this is why its better to put the content(summary) of external resources rather than external links – rahulserver Sep 11 '20 at 04:54
3

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.

shadyhill
  • 525
  • 5
  • 15
3

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*
    });
});
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
krishnazden
  • 1,127
  • 10
  • 19
  • I think `cors` requires the `express` package; without it you'll get this error (at least I did): "Cannot read properties of undefined (reading 'origin')" – thdoan Jun 09 '23 at 23:39
3

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

Thomas
  • 1,231
  • 14
  • 25
3
  1. Go into your Google Cloud Functions. You may have not seen this platform before, but it's how you'll fix this Firebase problem.
  2. 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.
  3. Find your function, click on the name.
  4. Go to the permissions tab. Click Add (to add user).
  5. Under new principles, type 'allUsers' -- it should autocomplete before you finish typing.
  6. Under select a role, search for Cloud Functions, then choose Invoker.
  7. Save.
  8. 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!");
});
Sercan
  • 4,739
  • 3
  • 17
  • 36
zqxyz
  • 124
  • 4
  • Wont this will make your function public and available to anyone if you don't handle the authentication yourself inside the function. – Nicholas Tsaoucis Feb 04 '22 at 11:50
  • For me, this is what it took to get the thing working and save my sanity. I worked backwards and implemented security measures from there. How that is handled is outside the scope of what I'm answering, but it is worth mentioning. – zqxyz Feb 06 '22 at 10:10
  • Update in April 2023: Click Add is now Click "GRANT ACCESS" but otherwise the instructions are as is. Hey... it wouldn't be the cloud if you could use instructions from a year ago :-) – Martin Capodici Apr 20 '23 at 09:45
2

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.

GorvGoyl
  • 42,508
  • 29
  • 229
  • 225
2

I got the error because I was calling a function that didn't exist on the client side. For example:

firebase.functions().httpsCallable('makeSureThisStringIsCorrect');
user1689987
  • 1,002
  • 1
  • 8
  • 23
1

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

Noks1
  • 11
  • 1
1

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))
Kevin Danikowski
  • 4,620
  • 6
  • 41
  • 75
1

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.

1

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.

Abraham
  • 12,140
  • 4
  • 56
  • 92
1

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 :

  1. install gsutil : https://cloud.google.com/storage/docs/gsutil_install#linux-and-macos

  2. 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

TriS
  • 3,668
  • 3
  • 11
  • 25
bousaque
  • 11
  • 3
0

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

Kacpero
  • 11
  • 4
0

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'
});
Agilan I
  • 212
  • 3
  • 5
0

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'
}));
Joel Walkley
  • 11
  • 1
  • 1
0

Use cors on your https.onRequest with Typescript like this:

import * as cors from 'cors';
const corsHandler = cors({origin: true});

export const pingFunctionWithCorsAllowed = functions.https.onRequest((request, response) => {
  corsHandler(request, response, () => {
    response.send(`Ping from Firebase (with CORS handling)! ${new Date().toISOString()}`);
  });
});

From Source

BorisD
  • 1,611
  • 17
  • 22
0

Cloud functions logging helps, check that if you are stuck.

My issue turned out to be a type error on my cloud function where I had a number where a string was expected:

TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received type number (1)

For some reason this gave me the cors error on front-end, and it became a few wasted hours.

lejlun
  • 4,140
  • 2
  • 15
  • 31
David
  • 151
  • 1
  • 5
0

I tried the below methods, but none worked.

  1. Installing the cors package.
  2. Adding the cors flag to the firebase.json file.
  3. returning cors as a part of request options.

The solution is to add a cors option to the function.

functions.https.onCall(handler, {
  cors: true
})

rbansal
  • 1,184
  • 14
  • 21
0

You can set the headers in firebase.json like this:

"hosting": {
  // ...

  // Applies a CORS header for all font files
  "headers": [ {
    "source": "**/*.@(eot|otf|ttf|ttc|woff|font.css)",
    "headers": [ {
      "key": "Access-Control-Allow-Origin",
      "value": "*"
    } ]
  } ]
}

More on Firebase docs.

bnitica
  • 11
  • 4