Firebase Callable Function + CORS

18,031

Solution 1

For anybody else who has arrived here searching firebase callable functions cors errors, here's my checklist:

  1. Ensure the function is deployed.
  2. Ensure the function name is correct. I was calling recalculatY when it should have been recalculateY. Got a cors error for some reason.
  3. Ensure the function code itself is not throwing an error. Use the emulator to help. This didn't throw a cors error still helpful to know.
  4. Ensure your regions match - I am using europe-west2. I had to both deploy the function with that region, and call it using the region. For a while, I assumed the client would infer the correct region if the function name was correct. That was not the case.

Deploying a callable function to a specific region:

// This is the file in which you define your callable function.
const functions = require('firebase-functions');
...
exports.yourFunc = functions.region('europe-west2').https.onCall(async (data, context) => {
    ...
})

Calling a function in a specific region from the client (in this case, a vuejs web app):

// In my case, this is a vuex store file, but it is safe to assume this is plain old javascript
import firebase from 'firebase/app'
import 'firebase/functions'
...
firebase.app().functions('europe-west2').httpsCallable('yourFunc')

Note: firebase.app().function... vs firebase.app.function...

Solution 2

For anyone looking at this post Jan 2020..

Found this answer on Reddit (https://www.reddit.com/r/reactjs/comments/fsw405/firebase_cloud_functions_cors_policy_error/)

Turns out on 15th Jan 2020, Google changed the security settings where all new functions no longer have a Cloud Functions Invoker. This means that all newly created functions will have their access forbidden, thus resulting in a CORS policy block.

Here is how you fix it, as it's not all that obvious:

https://cloud.google.com/functions/docs/securing/managing-access-iam#allowing_unauthenticated_function_invocation

Solution 3

I had this problem with some of my Firebase functions but not others. I eventually fixed it by doing this:

  1. Commenting the function out in index.js
  2. Running firebase deploy
  3. Entering y at the prompt to delete the function
  4. Waiting for 5 to 10 minutes
  5. Removing the comments around the function and running firebase deploy again

Without any changes to the function itself, it now runs without any CORS issues.

Solution 4

My issue was not with CORS, but with my error handler. Instead of rejecting the promise, I've used throw directly in the catch handler.

catch((err) => {
  throw new functions.https.HttpsError('unknown', err.message, err)
})

Solution 5

Probably many will hit this issue with the emulator and cors messages.

I havn't seen my case discussed in any discussion I've seen in Google, I do have seen many "can't reproduce", maybe my case will shade some light:

In my case the issue was that I wasn't running the hosting from the firebase emulator.

When you run your react app via npm start - while the functions run via firebase emulators:start, you will see the Cors errors.

So when testing cloud function calls, rather using npm start, you should do npm run build and then access the app from the emulator...

Search for something like: "hosting: Local server: http://localhost:5000"

few notes -

  • Your functions should also work against the emulator via

    const functions = firebaseApp.functions('europe-west3');// lets assume thats your region functions.useFunctionsEmulator('http://localhost:5000');

Share:
18,031
Pietro Coelho
Author by

Pietro Coelho

Updated on June 12, 2022

Comments

  • Pietro Coelho
    Pietro Coelho about 2 years

    I'm trying to call a callable Cloud Function from my app, but I'm facing CORS issues. enter image description here

    I can't enable Cors since I don't have access to the request and response on the onCall function. This is my function:

    exports.UserInvitation = functions.https.onCall((data, context) => {
      const email = data.email
    
    
      return new Promise((resolve, reject) => {
        admin.auth().createUser({
          email: email,
          emailVerified: false,
          password: password
        }).then(resolve).catch((err) => {
          console.error(err.code)
          reject(new functions.https.HttpsError(err.code, err.message))
        })
      })
    })
    

    And this is how I call it:

    functions.httpsCallable('UserInvitation')({ email: this.input.value }).then((data) => {
          console.log('Sent invitation:', data)
    })
    

    Firebase-functions package.json:

    {
      "name": "functions",
      "description": "Cloud Functions for Firebase",
      "scripts": {
        "serve": "firebase serve --only functions",
        "shell": "firebase functions:shell",
        "start": "npm run shell",
        "deploy": "firebase deploy --only functions",
        "logs": "firebase functions:log"
      },
      "dependencies": {
        "bluebird": "^3.5.1",
        "firebase-admin": "~5.12.0",
        "firebase-functions": "^1.0.1"
      },
      "private": true
    }
    

    WEB SDK Firebase version: 4.13.1

  • mesqueeb
    mesqueeb about 4 years
    that seems extremely weird to me. Rejecting inside a promise that you are returning in the cloud function, feels to me like it's the exact same thing as throwing...
  • moto
    moto about 4 years
    Good lord. What a mess of a bug to find. Thank you!
  • Kishan Oza
    Kishan Oza about 4 years
    but this will allow all users to call this function I mean I have done that CORS error gone but now I can trigger that function from postman with out any headers!! is this the only way @Kitson
  • Kitson
    Kitson about 4 years
    I was using .https.onCall(async (data, context) => { ... }) and the context has access to teh auth user context.auth. I was then using this to check permissions and throw an error for unauthenticated users.
  • akauppi
    akauppi about 4 years
    Where do you set the regions? I'm using one, but only in the calling: exports.myf = functions.region("europe-west3").https.onCall(...). Is there some other place I should touch?
  • akauppi
    akauppi about 4 years
    This made it for me! Didn't have region in the calling.
  • Code Spirit
    Code Spirit about 4 years
    You can wrap it in your own module and use this instead of the original functions module so you only have to call region once.
  • akauppi
    akauppi about 4 years
    My problem was solved by @Aido's answer. Needed to also have the browser code tell Firebase which region to use.
  • Séraphin
    Séraphin almost 4 years
    Basic checklist... you saved me with "Ensure the function name is correct"
  • Kevin Aung
    Kevin Aung almost 4 years
    Thanks for this. It was #1 for me. I thought I had deployed it.
  • Nithin
    Nithin over 3 years
    saved my day. I was gonna edit a whole lot of code.
  • Eric Crescioni
    Eric Crescioni over 3 years
    This is infuriating - for such a big company the docs are all over the place on this topic. How was that not all over the place when it happened? Thank you.
  • tmorell
    tmorell over 3 years
  • Séraphin
    Séraphin over 3 years
    Second time I land here for a typo in my function name. Thanks again!
  • dvdmmc
    dvdmmc over 3 years
    Thanks, this worked for me. Interesting tidbit to add is that I deployed 3 functions at the same time and only 1 had this issue.
  • sceee
    sceee about 3 years
    Unbelievable, after spending several hours trying all the different solutions here, I deleted every function and redeployed them again and suddenly, they started working without any CORS issues. During that time I was still unsure whether I would also have to do @Nikita's solution for https.onCall(..) functions where the user is authenticated (because nothing made them work). Answer is no - complete deletion and redeploy fixed the issue.
  • mesqueeb
    mesqueeb about 3 years
    I tried every single thing in this thread. But this one was the solution for me. Just delete all cloud functions once. Then redeploy and it works again!
  • Félix Paradis
    Félix Paradis about 3 years
    I did something extremely similar: deployed THE EXACT SAME FUNCTION with a different name: great success. Flipped a table and moved on.
  • 今際のアリス
    今際のアリス about 3 years
    I tried all kinds of solutions and yes, the solution was the same for me, just remove all the functions and deploy them again. What the actual.. I've been sitting with this error for hours wondering what and how to solve the issue and then it is just "delete and try again"... feel so stupid.
  • Ryan Prentiss
    Ryan Prentiss almost 3 years
    So yeah, I just spent the last 36 hours banging my head against this. Thank you.
  • Suat Karabacak
    Suat Karabacak almost 3 years
    I tried every other possible solution ... No offense but I tought this never gonna work because of that I even never tried that but man ... I can say this was the issue. Thank you !
  • Jeyhun Ashurbayov
    Jeyhun Ashurbayov over 2 years
    love you! ❤️ saved my day
  • Ruben
    Ruben over 2 years
    thanks that worked after I started my local emulator again. But do you also know why? What does the firebase environment have to do with my local emulator?
  • Eosis
    Eosis over 2 years
    I will also add my misery to this pile. Deleting the function from the console and re-deploying it was enough to get the functions working. 😑
  • Chrisk8er
    Chrisk8er over 2 years
    I vote for this solution. You saved my day man... Thanks
  • Witt
    Witt over 2 years
    Deploying to another region, then redeploying to the correct region seems to produce this. Deleting the function in the webAPI and redeploying did the trick. Thanks!
  • Mentor
    Mentor over 2 years
    This worked, and it makes me sad. In case Google can't find this: this is the fix to CORS errors for onCall firebase functions running into preflight check errors due to a suspected region error in GCP.
  • CiriousJoker
    CiriousJoker over 2 years
    The cors issue comes because when trying to call a non-existent function redirects you to Google's signin, which has cors enabled ofc
  • Street0
    Street0 about 2 years
    This shouldn't be a solution. allUsers leaves it open to Unauthorized access. Answer should consider restricting access to authorized users and consider registering some domain / origin to allow access. Not this
  • Street0
    Street0 about 2 years
    This just leaves it again with allUsers invoker which allows for Unauthorized access. People saying it's working again after redeploy is just because the recreated functions has allUsers invoker..
  • Jeroen van de Ven
    Jeroen van de Ven about 2 years
    I'm going to have to start trying this kind of solution earlier on in the troubleshooting process... deploying under a new name fixed it.