Enabling CORS in Cloud Functions for Firebase

182,127

Solution 1

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
    })
});

Solution 2

You can set the CORS in the cloud function like this

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

No need to import the cors package

Solution 3

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
});

Solution 4

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" }
]

Solution 5

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

Share:
182,127

Related videos on Youtube

Andrey Pokrovskiy
Author by

Andrey Pokrovskiy

Updated on July 23, 2022

Comments

  • Andrey Pokrovskiy
    Andrey Pokrovskiy almost 2 years

    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.

    • Kato
      Kato about 7 years
      Also a sample in the docs here
    • TheBen
      TheBen about 6 years
      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
    • Charles Harring
      Charles Harring about 4 years
      wrapping the incoming request in cors() like above was the only thing that worked for me
    • Antoine Weber
      Antoine Weber almost 4 years
      can you edit your "update" to underline that the cors middleware is required? This will save some people some time
  • Alan
    Alan over 6 years
    It looks like this is where the whitelist of domains to allow access is defined? And setting origin: true allows any domain to access? (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.
  • dSebastien
    dSebastien about 6 years
    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 :)
  • TheBen
    TheBen about 6 years
    @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
    TheBen about 6 years
    Not sure what you mean by hacking ? Care to elaborate a bit? Read your post but I don't see you mentioning it
  • TheBen
    TheBen about 6 years
    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. stackoverflow.com/q/50053798/5601401
  • Jim Factor
    Jim Factor almost 6 years
    this worked when other SO answers with setting the headers manually did not
  • Spiral Out
    Spiral Out over 5 years
    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!"); });
  • Oliver Dixon
    Oliver Dixon over 5 years
    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
    Oliver Dixon over 5 years
    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.
  • elverde
    elverde over 5 years
    This works perfectly for my case, a cloud function that makes a XHR call to Mailchimp API.
  • koljaTM
    koljaTM over 5 years
    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.
  • Vlad
    Vlad about 5 years
    @SpiralOut you can simply disable tslint
  • Jaap Weijland
    Jaap Weijland about 5 years
    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
  • Vlad
    Vlad about 5 years
    @SpiralOut i mean remove tslint command from firebase build script only
  • unplugged
    unplugged almost 5 years
    also make sure you add your [project-id] as this was the issue i faced
  • Alex Suzuki
    Alex Suzuki almost 5 years
    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: github.com/firebase/firebase-tools/issues/842
  • royappa
    royappa almost 5 years
    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.
  • Corey Cole
    Corey Cole over 4 years
    google cloud functions do not allow the wildcard origin: cloud.google.com/functions/docs/writing/…
  • Corey Cole
    Corey Cole over 4 years
    google cloud functions do not allow the wildcard origin: cloud.google.com/functions/docs/writing/…
  • Corey Cole
    Corey Cole over 4 years
    google cloud functions do not allow the wildcard origin: cloud.google.com/functions/docs/writing/…
  • Corey Cole
    Corey Cole over 4 years
    google cloud functions do not allow the wildcard origin: cloud.google.com/functions/docs/writing/…
  • Shah Rushabh
    Shah Rushabh over 4 years
    @CoreyCole I think that's only if you need to add the Authorization header. The above seems to work ok.
  • Stanislau Buzunko
    Stanislau Buzunko over 4 years
    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
  • Viktor Hardubej
    Viktor Hardubej over 4 years
    actually when I use onCall func on browser I got cors error. Could I set costom headers in this request ?
  • Gordon
    Gordon about 4 years
    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)
  • Object object
    Object object about 4 years
    Please provide some explanation of linked material in your answer, why is it relevant and such
  • Gustavo Garcia
    Gustavo Garcia about 4 years
    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!
  • Antonio Ooi
    Antonio Ooi about 4 years
    Where to place this line of code? Which part of the cloud function?
  • Antonio Ooi
    Antonio Ooi about 4 years
    TypeError: 'origin' is undefined.
  • Henrik Bøgelund Lavstsen
    Henrik Bøgelund Lavstsen about 4 years
    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
  • deanwilliammills
    deanwilliammills almost 4 years
    @AntonioOoi you can put it anywhere within the function
  • Antonio Ooi
    Antonio Ooi almost 4 years
    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.
  • Antoine Weber
    Antoine Weber almost 4 years
    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
  • Simon B.
    Simon B. almost 4 years
    @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...
  • Amina Darwish
    Amina Darwish over 3 years
    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
  • rahulserver
    rahulserver over 3 years
    That link is broken mhaligowski.github.io/blog/2017/03/10/… this is why its better to put the content(summary) of external resources rather than external links
  • Alok Prusty
    Alok Prusty over 3 years
    response.set('Access-Control-Allow-Origin', '*'); this works fine for me. Do check this solution by @deanwilliammills
  • zeroasterisk
    zeroasterisk over 3 years
    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)
  • Antoine Weber
    Antoine Weber over 3 years
    Doug, you forgot the return keyword in your snippet. It should be: return cors(req, res, () => {.. instead.
  • Doug Stevenson
    Doug Stevenson over 3 years
    @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.
  • Antoine Weber
    Antoine Weber over 3 years
    Ok it works without the return. But the sample function uses return for some reason. I guess I got confused by that inconsistency
  • Doug Stevenson
    Doug Stevenson over 3 years
    @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. ¯\_(ツ)_/¯
  • elersong
    elersong over 3 years
    I added that line into my cloud function, and my localhost fetch is still blocked by CORS policy.
  • perepm
    perepm over 3 years
    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
  • sideshowbarker
    sideshowbarker over 3 years
    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 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).
  • wisetap.com
    wisetap.com over 3 years
    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?
  • Cooper Scott
    Cooper Scott over 3 years
    I needed to npm i cors and @types/cors for this work. Thank you!
  • Fewfre
    Fewfre over 3 years
    For those also getting onCall cors error, try this post: stackoverflow.com/q/50278537/1411473
  • CloudWindMoonSun
    CloudWindMoonSun over 3 years
    @YayoArellano , thanks. Your answer helped me, however I made a slight change: corsHandler(request, response, () => { YOUR CODE HERE });
  • Jaromír Adamec
    Jaromír Adamec over 3 years
    In my case, the issue was that I wasn't logged in under the correct Firebase project (firebase use <project-name> on the command-line) before running the emulator.
  • Kevin Danikowski
    Kevin Danikowski about 3 years
    This is an ideal solution if you might need to add more handlers or have many functions
  • sceee
    sceee about 3 years
    @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"?
  • David
    David about 3 years
    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
    David about 3 years
    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.
  • WebDev-SysAdmin
    WebDev-SysAdmin almost 3 years
    using firebase Hosting? if yes, then your cloud function MUST be in "us-central1" region, this is still true in june 2021.
  • dcts
    dcts almost 3 years
    this is no longer possible.
  • Jag99
    Jag99 almost 3 years
    where do i put in my function body? I have posted my code here stackoverflow.com/questions/68646425/…
  • phreakhead
    phreakhead over 2 years
    Here's the link to the docs if anyone is curious: firebase.google.com/docs/hosting/full-config#rewrite-functio‌​ns
  • phreakhead
    phreakhead over 2 years
    Is there any way to use this rewrite with the httpCallable? Or do we need to resort to normal web functions at that point?
  • Craig Howell
    Craig Howell over 2 years
    I have tried almost all answers on this page and this is the only one that worked. Thank you!
  • wisetap.com
    wisetap.com over 2 years
    I'm happy that worked! :)
  • Bao Pham
    Bao Pham over 2 years
    @elersong check whether you have http rather than https for your localhost.
  • 1252748
    1252748 over 2 years
    @OliverDixon Can you explain "you risk the function content being prematurely ended inside the callback on long calls." please?
  • danday74
    danday74 over 2 years
    lose logging on cloud functions v it doesn't work === prefer the former
  • Nicholas Tsaoucis
    Nicholas Tsaoucis over 2 years
    Wont this will make your function public and available to anyone if you don't handle the authentication yourself inside the function.
  • zqxyz
    zqxyz over 2 years
    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.
  • Richmond
    Richmond about 2 years
    will this works for onCall too?
  • Todd Rylaarsdam
    Todd Rylaarsdam about 2 years
    @AntoineWeber does this approach work on a per-router basis as well?
  • ykonda
    ykonda almost 2 years
    only answer that worked for me!