I'm having CORS issues with a very simple app, took me about 10 minutes to code it and I've spent hours trying to fix this CORS error.
The frontend, written in React, makes a POST request to the Express backend using axios.
app.use(cors()) is called before the single route in my Express app.
And this is the axios request in my React app:
(await axios.post("http://localhost:3000/login", {username: username, password: password})).data.success
I'm getting this CORS error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at...
Everything works fine on localhost though.
Express code:
require('dotenv').config();
const createError = require('http-errors');
const express = require('express');
const cors = require('cors');
const compression = require('compression');
const app = express();
app.use(cors({origin: "*", allowedHeaders: ['Content-Type']}));
app.use(express.json());
app.use(compression());
app.use(express.urlencoded({extended: true}));
app.post("/login", (req, res) => {
const params = req.body;
if (params.username === process.env.USERNAME && params.password === process.env.PASSWORD)
return res.json({success: true});
else
return res.status(401).json({success: false});
});
app.use((req, res, next) => next(createError(404)));
app.listen(process.env.NODE_PORT, () => console.log("Listening on port " + process.env.NODE_PORT));
Current, not ideal, working solution:
Use the machine's IP instead of localhost.
(await axios.post("http://192.168.*.*:3000/login", {username: username, password: password})).data.success
As can be gleaned from the Axios source code, when the second parameter to post is an object (which is the case, here), Axios sets the request's Content-Type header to application/json.
This header value is such as to cause the browser to trigger CORS preflight. The server must then explicitly list Content-Type in the Access-Control-Allow-Headers header of the response to the preflight request; otherwise, CORS preflight will fail, resulting in a CORS error in your browser.
Note that the default configuration of the Express CORS middleware (which you are currently relying on) doesn't allow any headers.
Explicitly allow Content-Type in your CORS configuration. You can do so with the allowedHeaders property of the CORS middleware's configuration object.
You need to configure your cors options. The origin can be a string or array which is a whitelist of the sources allowed to make requests. You can even handle it with a function if you need it to be dynamic. Also you can allow or disallow methods, validate credentials, etc. Check the package readme
Cors is a security mechanism to block any try between different domains. For example you have your backend in a domain like: https://wordpress.com and you want to fetch your frontend from your domain https://example.com this prevents that anyone can get access to your endpoints to steal information but this should not be your only security mechanism
const corsOptions = {
origin: "http://localhost:3000",
methods: ["GET","POST"]
};
app.use(cors(corsOptions));
Use the machine IP instead of localhost.
await axios.post("http://192.168.*.*:3000/login", {username: username, password: password})).data.success`