Reputation: 915
I have a Google Cloud Function. I created credentials for my project and authorized http://localhost & http://localhost:3000 as origins. I also have a Google user account that I gave the cloudfunctions.functions.invoke role to. I confirm this by going to the cloud function in the console and expand the "Cloud Functions Invoker" item and see my account listed there.
I can successfully access the function with curl.
curl https://[google-cloud-server]/test5 -H "Authorization: bearer my-identity-token"
However, if I try to invoke the function from my React app (I tried both axios and fetch), I get the following error....
Access to XMLHttpRequest at 'https://[google-cloud-server]/test5?a=b' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
A couple things to note...
I added so many tags to this post because I really don't know which layer is causing the problem. I'm probably doing something really obvious/stupid, but I'm out of ideas!
Cloud function....
exports.test5 = (req, res) => {
console.log('function invoked');
// Set CORS headers for preflight requests
// Allows GETs from any origin with the Content-Type header
// and caches preflight response for 3600s
res.set('Access-Control-Allow-Origin', '*');
if (req.method === 'OPTIONS') {
console.log('Determined it is OPTIONS request');
// Send response to OPTIONS requests
res.set('Access-Control-Allow-Methods', 'GET');
res.set('Access-Control-Allow-Headers', 'Authorization');
res.set('Access-Control-Max-Age', '3600');
res.status(204).send('');
} else {
console.log('Main function body');
res.send('Hello World!');
}
};
Call from React client...
const config =
{
params: payload,
headers:
{
Authorization: `bearer ${window.IDENTITY_TOKEN}`
}
};
axios.get(url, config)
.then((res) => {
...
})
.catch((err) => {
handleError(err);
});
Any ideas? Thanks
Upvotes: 2
Views: 3110
Reputation: 8074
CORS preflight OPTION request does not have an Authorization header and Cloud functions IAM prevalidates the Authorization header and will not call the function if it is missing.Therefore in order to serve the CORS preflight response you have to allow allUsers access to your cloud function.
They updated the documentation
If you want to build a web app that is secured with Google Sign-in and Cloud Functions IAM, you'll likely have to deal with Cross-Origin Resource Sharing (CORS). CORS preflight requests are sent without an Authorization header, so they will be rejected on all non-public HTTP Functions. Because the preflight requests fail, the main request will also fail.
To work around this, you can host your web app and function(s) on the same domain to avoid CORS preflight requests. Otherwise, you should make your functions public and handle CORS and authentication in the function code.
Alternatively, you can deploy a Cloud Endpoints proxy and enable CORS. If you want authentication capabilities, you can also enable Google ID token validation, which will validate these same authentication tokens.
Upvotes: 4