Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to solve CORS in firebase functions enviroment?

I´m runnig into CORS issues. In my functions/index.js I have:

const cors = require('cors')({
  origin: true
});

My endpoint is https://sis-t.redsys.es:25443/sis/realizarPago. I need to do a POST to this url with apropiate parameters from the client, and this is outside firebase enviroment. I also have the correct plan to allow external network, but making a request to a different address than the origin one, triggers a CORS problem:

  • error log
  • network log

I have read that you only need to modify the headers, but that only applies if you are making a request to your own server. When you do the http.onRequest(), you can use a middleware inside the function, but what happens when you make a POST to an external server?

This is the axios functions that do the POST:

cardPay: function () {
  this.cardProcess = true
    axios({
      method: 'post',
      url: 'https://us-central1-cutre-windrider.cloudfunctions.net/cardPay',
      data: {
        verifiedUserLogged: this.userLogged.uid,
        cart: this.cartItemList,
        finalPrice: this.serverPrice,
        deliveryInfo: this.userLogged.deliveryAdress,
        name: this.userLogged.displayName || false,
        email: this.userLogged.email
      }
    })
    .then(response => {
      this.requestData = response
      this.redsysRedirect(response.data.data)
    })
    .catch(console.log)
    },
redsysRedirect: function (data) {
  axios.post('https://sis-t.redsys.es:25443/sis/realizarPago', {
    'Ds_SignatureVersion': 'HMAC_SHA256_V1',
    'Ds_MerchantParameters': data.merchantParameters,
    'Ds_Signature': data.signature
  }).then(console.log).catch(console.log)

These are the server side functions:

exports.cardPay = functions.https.onRequest((req, res) => {
  return cors(req, res, () => {
    const cart = req.body.cart
    const user = req.body.verifiedUserLogged
    const key = admin.database().ref(`sales/${user}`).push().key
    processCart(cart).then(result => {
      console.info(createPayment(result, key))
      return res.json({ "data": createPayment(result, key) }).end()
    }).catch(console.log)
  })
})

function processCart(cart) {
  return new Promise((resolve, reject) => {
    Promise.all(cart.map(i => switcher(i)))
      .then(prices => resolve(
        prices.reduce(
          (finalPrice, price) => price + finalPrice, 0)
      )).catch(console.log)
  });
}

function switcher(item) {
  switch (item.destiny) {
    case 'bookedLessons':
        return lessonPrice(item.name, item.index)
      case 'bookedRentals':
        return rentalPrice(item.id, item.index, item.insurancePurchased, item.insuranceId)
      case 'bookedLodgins':
        return item.reservationData ? roomPriceWithReservation(item.id, item.quantity, item.persons, item.reservationData) : roomPriceNoReservation(item.id, item.quantity, item.persons)
      case 'deliveries':
        return productPrice(item.id, item.quantity)
      case 'bookedCar':
        return carPrice(item.id, item.index)
      case 'bookedStorage':
        return storagePrice(item.index)
      case 'bookedTransportation':
        return transportationPrice(item.id, item.index, item.persons, item.roundTrip)
      case 'bookedDoublePack':
        return doublePack(item.id, item.persons)
      case 'bookedTriplePack':
        return triplePack(item.id, item.persons)
      default:
        break
  }
}

function createPayment(total, orderId) {
  let redsys = new Redsys();
  let mParams = {
      "DS_MERCHANT_AMOUNT":total.toString(),
      "DS_MERCHANT_ORDER":orderId,
      "DS_MERCHANT_MERCHANTCODE":   "025988262",
      // "DS_MERCHANT_MERCHANTCODE":tpvInfo.fucCode,
      "DS_MERCHANT_CURRENCY":"978",
      // "DS_MERCHANT_CURRENCY":tpvInfo.currency,
      "DS_MERCHANT_TRANSACTIONTYPE":"0",
      // "DS_MERCHANT_TRANSACTIONTYPE":tpvInfo.transaction_type,
      "DS_MERCHANT_TERMINAL":   "001",
      // "DS_MERCHANT_TERMINAL":tpvInfo.terminal,
      "DS_MERCHANT_MERCHANTURL":'http://localhost:8080',
      "DS_MERCHANT_URLOK":'http://localhost:8080/home?foo=true',
      "DS_MERCHANT_URLKO":'http://localhost:8080/home?foo=false'
  };
  return  {signature: redsys.createMerchantSignature(/* tpvInfo.secret */   "sq7HjrUOBfKmC576ILgskD5srU870gJ7", mParams) , merchantParameters: redsys.createMerchantParameters(mParams), raw: mParams};
}
like image 461
mrsalitre Avatar asked Oct 01 '18 18:10

mrsalitre


People also ask

How do you turn off Cors in firebase?

Configuring CORS (Cross-Origin Resource Sharing) request has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. You can also explicitly disable CORS by setting the cors option to false for your function.

What is the difference between onCall HTTP callable and onRequest HTTP request functions?

onRequest creates a standard API endpoint, and you'll use whatever methods your client-side code normally uses to make. HTTP requests to interact with them. onCall creates a callable. Once you get used to them, onCall is less effort to write, but you don't have all the flexibility you might be used to.

What is firebase function?

Cloud Functions for Firebase is a serverless framework that lets you automatically run backend code in response to events triggered by Firebase features and HTTPS requests. Your JavaScript or TypeScript code is stored in Google's cloud and runs in a managed environment.


2 Answers

For someone who will meet this issue in the future (or my future self):

If you've already configured CORS using cors package, and you think you configured it correctly, and still have CORS error in the browser console, check this article:

https://haha.world/firebase-cors/

Basically, it's a misleading error returns from Google Cloud Functions, when actually the error is inside your code logic (which is totally not related to CORS at all)

So the first step to fix this bug is to check Google Cloud Functions logs (or Firebase Cloud Functions logs) to see if your function crashed because of any error in your code. Then fix it.


Note: For someone that doesn't have the issue that I described above, you can see other answers, or check these resources:

  1. https://expressjs.com/en/resources/middleware/cors.html
  2. https://firebase.google.com/docs/functions/http-events#using_existing_express_apps
like image 172
Hoang Trinh Avatar answered Sep 20 '22 10:09

Hoang Trinh


Within your Firebase Function response header you could explicitly allow all origins:

exports.handler = ((req, res) => {
    res.set({ 'Access-Control-Allow-Origin': '*' }).sendStatus(200)
})

Or you could modify this to allow only specific origins. This is generally how I have worked around CORS issues with Firebase funcitons in the past.

like image 21
Jason Dark Avatar answered Sep 21 '22 10:09

Jason Dark