CORS policy error calling Cloud Function HTTP trigger - javascript

I wrote and deployed a Firebase Cloud function with CORS support:
const cors = require('cors')({
origin: true
});
...
exports.test = functions.https.onRequest((req, res) => {
cors(req, res, () => {
const idToken = req.query.idToken;
admin.auth().verifyIdToken(idToken)
.then((decoded) => {
var uid = decoded.uid;
return res.status(200).send(uid);
})
.catch((err) => res.status(401).send(err));
});
});
I call the HTTP Trigger from my React app using the Axios package:
firebase.auth().currentUser.getIdToken(/* forceRefresh */ true).then(function(idToken) {
// Send token to your backend via HTTPS
// ...
console.log(idToken);
axios.get('https://XXX.cloudfunctions.net/test?idToken='+idToken)
.then(response => console.log(response));
}).catch(function(error) {
// Handle error
});
Unfortunately, when running the app on my local server, I still get an error:
Failed to load...Redirect From..to..
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
PS. I have used the procedure reported here

I found an answer here
exports.test = functions.https.onRequest((req, res) => {
cors(req, res, () => {});
const idToken = req.query.idToken;
admin.auth().verifyIdToken(idToken)
.then((decoded) => {
var uid = decoded.uid;
return res.status(200).send(uid);
})
.catch((err) => res.status(403).send(err));
});

Related

Firebase Cloud Functions CORS issue

I have CORS installed for firebase cloud functions.
I'm using sendgrid to send a transactional email.
I was using this EXACT code in another folder and this function was returning no problem - but I merged 2 separate documents of functions into one and now I keep getting the error...
Access to XMLHttpRequest at 'cloud function trigger' from origin 'my website' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Really confused as to what it could be...
const cors = require('cors')({ origin: true });
exports.sendRequest = functions.https.onRequest((req, res) => {
cors(req, res, () => {
return Promise.resolve()
.then(() => {
if (req.method !== 'POST') {
const error = new Error('Only POST requests are accepted');
error.code = 405;
throw error;
}
const msg = {
to: req.body.companyEmail,
from: req.body.name,
text: 'and easy to do anywhere, even with Node.js',
html: '<strong>and easy to do anywhere, even with Node.js</strong>'
}
};
return sgMail.send(msg);
})
.then((response) => {
if (response.body) {
res.send(response.body);
} else {
res.end();
}
})
.catch((err) => {
console.error(err);
return Promise.reject(err);
});
})
})

Google Drive OAuth 2.0 Invalid grant_type

Following the example from OAuth2WebServer from google I'm trying to set up an authentication flow from an express app using the HTTP/REST method they have but with every request I am returned with an error
I went through Google OAuth “invalid_grant” nightmare — and how to fix it but unfortunately it did not help.
{
error: "unsupported_grant_type",
error_description: "Invalid grant_type: "
}
This is a shortened version of the error I am receiving. If you need to see more of the error let me know and I can post it.
Server
const express = require('express');
const axios = require('axios');
const { web } = require('./src/client_id.json');
const app = express();
const { client_id, client_secret } = web;
let count = 0;
app.use(express.json());
/*************************
** REDIRECT USER TO GOOGLE AUTH **
*************************/
app.get('/', (req, res) => {
const redirect_uri = 'http://localhost:5000/auth';
const scope = 'https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.metadata.readonly';
const access_type = 'offline';
res.redirect(`https://accounts.google.com/o/oauth2/v2/auth?scope=${ scope }&access_type=${ access_type }&redirect_uri=${ redirect_uri }&response_type=code&client_id=${ client_id }`);
});
/*************************
** ON AUTH WE EXCHANGE ACCESS TOKEN FOR REFRESH TOKEN **
*************************/
app.get('/auth', (req, res) => {
count++;
if (count >= 2) {
return res.redirect('http://localhost:3000');
}
const { code } = req.query;
const redirect_uri = 'http://localhost:5000/auth';
const grant_type = 'authorization_code';
axios.post('https://www.googleapis.com/oauth2/v4/token', {
code,
client_id,
client_secret,
redirect_uri,
grant_type
}, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(data => {
console.log(data)
res.redirect('http://localhost:3000');
})
// ALWAYS HITS THE CATCH "Invalid grant_type"
.catch(err => {
console.log(err);
console.log('ERROR')
});
});
app.listen(5000, console.log('Server listening on port 5000'));

Firebase Functions + CORS

Having an issue with a firebase function that I need to work with cors. Based off the documentation and all the posts I've read it should be working but seem's like no matter what I try I keep getting the same error:
Failed to load <URL>: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 500.
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
And here is the corresponding code in my firebase functions index.js file:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const cors = require('cors')({origin: true});
const stripe = require('stripe')('<TEST_KEY>');
const gcs = require('#google-cloud/storage')({keyFilename: '<PATH_TO_KEY>'});
const Easypost = require('#easypost/api');
const api = new Easypost('<TEST_KEY>');
admin.initializeApp(functions.config().firebase);
exports.processOrder = functions.https.onRequest((req, res) => {
cors(req, res, () => {
var body = JSON.parse(req.body);
if (
!body.shipment_id ||
!body.items ||
!body.card
) return res.set('Access-Control-Allow-Origin', '*').send({error: true, message: 'Missing information'});
getPrices(body.items, (err, prices, totalPrice) => {
if (err) return res.set('Access-Control-Allow-Origin', '*').send({error: err, message: "Error"})
// Create a new customer and then a new charge for that customer:
stripe.customers.create({
email: 'test#example.com'
}).then((customer) => {
return stripe.customers.createSource(customer.id, {
source: body.card.token.id
});
}).then((source) => {
return stripe.charges.create({
amount: (totalPrice * 100),
currency: 'usd',
customer: source.customer
});
}).then((charge) => {
return res.set('Access-Control-Allow-Origin', '*').send({error: false, message: "Success"});
}).catch((err) => {
console.log(err);
return res.set('Access-Control-Allow-Origin', '*').send({error: err, message: "Error"});
});
});
});
});
Any help would be greatly appreciated :)
Edit: Just wanted to note: I've tried only setting res.set('Access-Control-Allow-Origin', '*') and not using the cors middleware, and I've tried not setting the header and only using cors. Neither of which worked :(
Solution: As #sideshowbarker said in a comment, my function had an error elsewhere before returning. The Access-Control-Allow-Origin was never even getting set. Once I fixed the error it was all good! Ty!
In node you can use a package to solve this problem. To enable all CORS install the following package:
npm install cors
Then assuming you are using express you can then enable CORS by the following lines of code:
var cors = require('cors');
app.use(cors());

Preflight request in VueJS with axios

I am a bit stuck with getting a response from the meetup API. The error I am getting:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
Here's my code:
var config = {'Access-Control-Allow-Headers': 'Authorization'}
axios.get(`https://api.meetup.com/self/calendar?&sign=true&photo-host=public&page=20`, {headers: config})
.then(response => {
console.log(response.data)
this.posts = response.data
})
.catch(e => {
this.errors.push(e)
})
I've read a little bit on CORS here Cross-Origin Resource Sharing (CORS) but all my attempts in getting this to work have failed.
Can any of you shed some light on this?
Thanks,
Manu
your api is not served on same host. either use reverse proxy like nginx or use cors toggle extension.
Right, I got this working now. Both #FailedUnitTest and #Manav Mandal suggestions are worth considering. However, instead of using OAuth you can use an API key - which I found easier. Also, my proxy is my expressJS server.
On the server side you would have something along the following lines:
var express = require('express');
var axios = require('axios');
// meetup API
var instance = axios.create({
baseURL: 'https://api.meetup.com/'
});
app.get('/anything', function(req, res) {
const apiKey = 'yourKey';
const isSigned = 'true';
const photoHost = 'public';
const pageCount = '20';
const url = '/self/calendar?' + 'key=' + apiKey + '&sign=' + isSigned
+ '&photo-host=' + photoHost + '&page=' + pageCount + '';
instance.get(url)
.then(response => {
return res.send(response.data);
})
.catch(e => {
return e;
})
});
And the client side:
data () {
return {
cards: [],
errors: []
};
},
created () {
axios.get('/anything')
.then(response => {
this.cards = response.data;
})
.catch(e => {
this.errors.push(e);
});
}
Make sure both your server and your client run over the same port.
Regards,
Manu

express + cors() is not working properly

I'm building a React application and I'm trying to make a call to https://itunes.apple.com/search?term=jack+johnson
I have a helper called requestHelper.js which looks like :
import 'whatwg-fetch';
function parseJSON(response) {
return response.json();
}
function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response;
}
const error = new Error(response.statusText);
error.response = response;
throw error;
}
export default function request(url, options) {
return fetch(url, options)
.then(checkStatus)
.then(parseJSON);
}
So I get:
XMLHttpRequest cannot load
https://itunes.apple.com/search?term=jack%20johnson. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:3000' is therefore not allowed
access.
My express server looks like this:
const ip = require('ip');
const cors = require('cors');
const path = require('path');
const express = require('express');
const port = process.env.PORT || 3000;
const resolve = require('path').resolve;
const app = express();
app.use(cors());
app.use('/', express.static(resolve(process.cwd(), 'dist')));
app.get('*', function(req, res) {
res.sendFile(path.resolve(resolve(process.cwd(), 'dist'), 'index.html'))
});
// Start app
app.listen(port, (err) => {
if (err) {
console.error(err.message);
return false;
}
const divider = '\n-----------------------------------';
console.log('Server started ✓');
console.log(`Access URLs:${divider}\n
Localhost: http://localhost:${port}
LAN: http://${ip.address()}:${port}
${divider}
`);
});
I have tried using mode: 'no-cors' but is not actually what I need since the response is empty.
Am I doing something wrong with this configuration?
The same origin policy kicks in when code hosted on A makes a request to B.
In this case A is your Express app and B is iTunes.
CORS is used to allow B to grant permission to the code on A to read the response.
You are setting up CORS on A. This does nothing useful since your site cannot grant your client side code permission to read data from a different site.
You need to set it up on B. Since you (presumably) do not work for Apple, you can't do this. Only Apple can grant your client side code permission to read data from its servers.
Read the data with server side code instead.

Categories

Resources