-1

I'm facing a CORS policies issues with Firebase functions even though I think I'm doing the right thing in the backend, I'll show you the code.

const cors = require("cors");
const express = require("express");
const cookieParser = require('cookie-parser');
const app = express();
app.use(
    cors({
        origin: true,
        credentials: true
    }),
    cookieParser(),
);

This is the function I'm trying to call from the frontend:

app.post("/auth/login", (req, res) => login(req, res));

With this body:

const login = async (req, res) => {
  try {
    const user = {
      id: req.body.id,
      password: req.body.password,
    };

    const auth = getAuth();

    const { valid, errors } = validateLoginData(user);

    if (!valid)
      throw { code: "validation-failed", message: errors, status: 400 };

    let data = await signInWithEmailAndPassword(auth, user.id, user.password);
    let token = await data.user.getIdToken();

    console.log("TOKEN: " + token);

    res.cookie("_token", token, { httpOnly: true, maxAge: 3600000 });

    return res.status(202).json({ message: "OK" });
  } catch (err) {
    switch (err.code) {
      case "validation-failed":
        return res.status(err.status).json({ message: err.message });

      case "auth/user-not-found":
      case "auth/wrong-password":
        return res
          .status(401)
          .json({ message: "Wrong credentials, please try again" });

      default:
        return res.status(500).json({ message: err.message });
    }
  }
};

So here's the problem: when I call this from postman it works, when I call this from my browser (Brave) it doesn't work and it tells me this in the console:

Access to XMLHttpRequest at 'https://europe-west1-stormtestfordota.cloudfunctions.net/api/auth/login' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

I've tried with many fixes that I found online but none has worked, can you help me please?

MarioG8
  • 3,423
  • 4
  • 6
  • 20
Allennick
  • 177
  • 7
  • Regardless of your issue, do you understand the serious security implications of allowing any origin with credentials as you do here? – jub0bs Dec 18 '21 at 11:59
  • Yes! But we have security rules set up to prevent any malicious act – Allennick Dec 18 '21 at 12:52
  • How do you protect users against cross-origin request forgery? – jub0bs Dec 18 '21 at 12:54
  • We use http only cookies to ensure that everything works fine – Allennick Dec 18 '21 at 13:14
  • The `HttpOnly` cookie attribute does nothing against CSRF attacks... Please reconsider your CORS configuration and understand what you're doing. – jub0bs Dec 18 '21 at 13:41
  • I am getting a 404 from Postman for "https://europe-west1-stormtestfordota.cloudfunctions.net/api/auth/login' – Gourav B Dec 20 '21 at 11:03
  • @Allennick Did you make any progress on this? I tried to help with an answer below. Did you have a chance to check that out, and did it make sense? If my answer was useful, click the upvote button (▲) to the left of it. If it answered your question, click the checkmark (✓) to accept it. That way others know that you've been (sufficiently) helped. – Priyashree Bhadra Dec 21 '21 at 13:39

1 Answers1

0

CORS is a node.js package for providing Express middleware that can be used to enable CORS with various options.

  • Enable all CORS requests
  • Enable CORS for a single route
  • Configuring CORS
  • Configuring CORS with dynamic origin
  • Enable CORS Preflight
  • Enable CORS asynchronously

If you want to use Express and CORS middleware like that, you should try onRequest functions as shown below:

const express = require('express');
const cors = require('cors'); 
const app = express(); // Automatically allow cross-origin requests 
app.use(cors({ origin: true })); // build multiple CRUD interfaces:
app.get('/test2', (req, res) => { //Handle your test2 methods here
return res.send('your response') 
}); // Expose Express API as a single Cloud Function: 
exports.api = functions.https.onRequest(app);
 

Now in this case the CORS middleware you wrote will be running. Your function's URL may look something like - https://us-central1-myapp.cloudfunctions.net/api Then to use the /test2 route it becomes https://us-central1-myapp.cloudfunctions.net/api/test2. CORS shouldn't be an issue anymore here but do note it's an express app now so the parameters in the function are Request, Response instead of data, context.

Also try to follow the steps outlined on https://cloud.google.com/functions/docs/samples/functions-http-cors#functions_http_cors-nodejs and the function will look something like below as in this

exports.hello = functions.https.onRequest((request, response) => {
response.set('Access-Control-Allow-Origin', '*'); 
response.set('Access-Control-Allow-Credentials', 'true'); // vital 
if (request.method === 'OPTIONS') { // Send response to OPTIONS requests
response.set('Access-Control-Allow-Methods', 'GET'); 
response.set('Access-Control-Allow-Headers', 'Content-Type'); 
response.set('Access-Control-Max-Age', '3600'); 
response.status(204).send(''); 
} 
else {
 const params = request.body; 
const html = 'some html'; 
response.send(html)
 } )};

Also have this essential reading on CORS for better understanding of the issue.

Priyashree Bhadra
  • 2,257
  • 1
  • 15