firebase / firebase-functions

Firebase SDK for Cloud Functions
https://firebase.google.com/docs/functions/
MIT License
1.01k stars 202 forks source link

HTTPS Request returns CORS errors even with the domain added as allowed origin #1530

Closed essequie1 closed 3 months ago

essequie1 commented 4 months ago

Related issues

[REQUIRED] Version info

node: v18.19.1

firebase-functions: ^4.3.1

firebase-tools: 13.3.1

firebase-admin: ^11.8.0

[REQUIRED] Test case

[REQUIRED] Steps to reproduce

I have an express app in a cloud function, it looks like this:

const app = express();

app.get("/", (_, res) => {
  res.status(200).send({ tests: "The best app" });
});

exports.app = onRequest(
  {
    region: "southamerica-east1",
    secrets: [xxxxx],
    cors: ["mydomain.com", "admin.mydomain.com"],
  },
  app
);

When i try to perform an https request from an app in "admin.mydomain.com" (hosted with firebase), i get a CORS error:

image

[REQUIRED] Expected behavior

I just want to perform https requests from the allowed origins I write in the CORS option of the request.

[REQUIRED] Actual behavior

Were you able to successfully deploy your functions?

Yes, no errors whatsoever when deploying, locally i have cors disabled though

google-oss-bot commented 4 months ago

I found a few problems with this issue:

inlined commented 3 months ago

After much debugging, I've figured out the issue. The access-control-allow-origins header only accepts a single origin or "*". To work around this, whenever the cors middleware is passed anything but a string for the origin object, it calculates the access-control-allow-origin header dynamically based on the origin header of the request. I've made a change to the SDK to turn arrays of a single string into a string to avoid this dynamic behavior where possible, but in your case, you'll have to make sure that your requestor includes the "origin" header.

inlined commented 3 months ago

Upon further debugging, it seems like using an express app or router as your callback also breaks CORS. I was unable to fix it even when modifying our code to use express apps as well. It seems you have two paths to making your code work:

// using an app:
const app = express();

app.use(cors({ origin: ["mydomain.com", "admin.mydomain.com"]}));
app.get("/", (_, res) => {
  res.status(200).send({ tests: "The best app" });
});

exports.app = onRequest(
  {
    region: "southamerica-east1",
    secrets: [xxxxx],
  },
  app
);

or

// using raw callbacks:
exports.app = onRequest(
  {
    region: "southamerica-east1",
    secrets: [xxxxx],
    cors: ["mydomain.com", "admin.mydomain.com"],
  },
  (_, res) => res.status(200).send({ tests: "The best app" }),
);
inlined commented 3 months ago

Sorry; tagged the wrong code change in this issue.