Firebase Callable Function + CORS
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
For anybody else who has arrived here searching firebase callable functions cors errors, here's my checklist:
- Ensure the function is deployed.
- Ensure the function name is correct. I was calling
recalculatY
when it should have beenrecalculateY
. Got a cors error for some reason. - 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.
- 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. - This last point is easy to oversee as everything else in the Firebase universe is more or less plug-and-play, but you need to make sure your functions are accessible by giving them the right permission. (This point is taken from @kitson's answer below. As many only read the first answer I think it is important to highlight this.)
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...