Firefox CORS failure with express node server - node.js

I'm using Express.js with the CORS middleware. I'm getting very strange behavior on Firefox v73.0.1 (64-bit)
Clean firefox profile... so nothing is cached.
I try a direct request to http://localhost/search?q=AMZN, I get results as expected.
I open my webapp which is running on localhost:3000. All of these requests are not using TLS/SSL.
I get "Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost/search?q=AMZN. (Reason: CORS request did not succeed)." when it tries to reach out to the API server backend.
I refresh the other tab where I was accessing localhost directly (same request which succeeded before), and I get a "connection reset".
Chrome does not do this...
I have been looking at wireshark and Firefox simply sends a GET request (several of them? Why?? I'm only making one), sends the headers and such, then it is followed by connection reset.
Sounds like node is doing something wrong? Or I dunno.
const express = require('express');
const fetch = require('node-fetch');
const util = require('util');
const app = express();
const port = 80;
var cors = require('cors')
var copts = {
origin: function (origin, callback) {
console.log('yeah');
// allow all
callback(null, true);
}
}
const SEARCH_URL = 'https://api.stocktwits.com/api/2/streams/symbol/%s.json';
app.get('/search', cors(copts), (req, res) => {
The "yeah" part never is hit at all.
Very simple clientside code.
return fetch(BACKEND_URL + uri).then(response => {
Tried removing CORS middleware and added these headers, based on examining github's cross-browser request-response in chrome
res.header('Access-Control-Allow-Methods', 'GET');
res.header('Access-Control-Max-Age', '3600');
res.header('Vary', 'Origin, Access-Control-Request-Headers, Access-Control-Request-Method, Accept-Encoding');
res.header('Access-Control-Allow-Origin', '*');
I didn't really have the options handler captured so maybe this didnt matter. I found those headers in the GET response.

It might be possible that the node server get crashed on an invalid reqeust and hence you are getting the reset error.
With cors package:
You need to add optionsSuccessStatus property in the cors options for some legacy browsers. And OPTIONS handler To enable pre-flightin requests.
const express = require('express');
const fetch = require('node-fetch');
const util = require('util');
const app = express();
const port = 80;
var cors = require('cors')
var copts = {
origin: function (origin, callback) {
console.log('yeah');
callback(null, true);
},
optionsSuccessStatus: 200
}
app.options("*", cors(copts));
const SEARCH_URL = 'https://api.stocktwits.com/api/2/streams/symbol/%s.json';
app.get('/search', cors(copts), (req, res) => { });
With headers.:
You are missing Access-Control-Allow-Headers in the response headers, you need to add the Access-Control-Allow-Headers header in the response header to allow the Access-Control-Allow-Origin header.
Try this.
const express = require('express');
const fetch = require('node-fetch');
const util = require('util');
const app = express();
const port = 80;
var cors = require('cors')
var copts = {
origin: function (origin, callback) {
console.log('yeah');
// allow all
callback(null, true);
}
}
const SEARCH_URL = 'https://api.stocktwits.com/api/2/streams/symbol/%s.json';
app.get('/search', (req, res) => {
res.header('Access-Control-Allow-Methods', 'GET, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Origin');
res.header('Access-Control-Allow-Origin', '*');
res.status(200).send("Ok")
});

in my case, FireFox removes the request header from ajax to a http url, but works fine with https

Have you updated your front end package.json file with the following?
"proxy": "http://localhost:[your port here]/",

try assigning CORS to the express server like so:
const cors = require('cors');
app.use(cors());

Related

HTTPS Server CORS Issue

So I have a NodeJS Express server which I am switching over from http to https. I have two files starting this:
app.js which defines the express part of the server, sets headers etc...
const express = require('express');
const app = express();
const dataRoutes = require('./routes/data');
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*"); //"https://www.wordleleague.org");
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
next();
})
app.use("/api/data", dataRoutes);
module.exports = app;
and server js which is the main part of the code, the launched file:
const app = require("./app");
const https = require("https");
const fs = require("fs");
const port = normalizePort(process.env.PORT || "3000");
app.set("port", port);
const httpsOptions = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
};
const server = https.createServer(httpsOptions, app);
server.listen(port);
Whilst this all worked fine when I was using http, now I get a CORS error when trying to query this:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at https://localhost:3000/api/data/login. (Reason:
CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 499.
It looks like the express app object isnt being used by the createServer. This all worked in http but its when I tried adding the credentials to the object for https that it went wrong.
If there is any further info anybody needs I am happy to provide, but this seems like all that is relevant. The requests are not being routed to the appropriate method and the http call from the angular app is definatele working.
Edit - The call to the server and more error detail
This is the code which calls the server:
this.subscriptions['leaguesub'] = this.http.get<{success: boolean, data: League[]}>(environment.apiUrl+'api/data/all/userId=' + id).subscribe({
next: (result: {success: boolean, data: League[]}) => {
this.leaguesLocal = [...result.data];
this.leagues.next([...this.leaguesLocal]);
}})
Works fine when I am using http. The only header which is added is an authorisation token:
req.headers.set('Authorization', "Bearer " + token)
The error it seems is a 499:
Status 499 Request has been forbidden by antivirus Referrer Policy
strict-origin-when-cross-origin
edit 2
If I reverse the order of createserver arguments then the CORs issue goes away but I have a new, different CORs issue:
const server = https.createServer(app, httpsOptions);
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at https://localhost:3001/api/user/login. (Reason:
CORS request did not succeed). Status code: (null).
One of the comments suggests using a CORs module but im not sure why my code isnt working
edit 3
Ok so I modified the main app.js express file to reflect the CORS suggestion made below:
const cors = require('cors');
const app = express();
app.use(cors());
And the error is persistent. Still no luck connecting to the server or any idea how to debug it. I tried using these methods to check a connection:
app.post("*", (req, res, next) => {
console.log(`post here`);
next();
})
app.get("*", (req, res, next) => {
console.log(`get here`);
next();
})
But alas I get no info from the concole about these running the event of a call being made to the API. Same errors as before.
edit 4
Running in Chrome gives me a new info source:
ERR_SSL_VERSION_OR_CIPHER_MISMATCH
Looking this up it seems there may be a problem with the SSL certificate. It is a self created SSL certificate which normally requires you to press ALLOW or something. It would explain why there seems to be nothing getting through to the server whatsoever as my browser is blocking it.
The problem then it how to get around this?

No 'Access-Control-Allow-Origin' header is present on the requested resource in Express app

I have an Express app running on same server with my Web app. I'm trying to make a XMLHttpRequest to my Express app and I get this error:
Access to XMLHttpRequest at 'http://10.0.0.222:9999/' from origin 'http://10.0.0.222:8080' 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.
Though in my app this header is clearly 'present'.
App code:
var cors = require('cors')
const util = require('util');
var inspect = require('eyes').inspector({maxLength: false})
const express = require('express');
var bodyParser = require('body-parser')
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var corsOptions = {
origin: 'http://10.0.0.222:8080',
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
}
app.post('/', cors(corsOptions), function (req, res) {
console.dir(req.body, {depth: null});
res.send('a');
});
const PORT = process.env.PORT || 9999;
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}...`);
});
XMLHttpRequest Code:
var xhr = new XMLHttpRequest();
xhr.open("POST", 'http://10.0.0.222:9999', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(goodJSON)
Why do I still get this error even though the origin option has my web app's host included?
It won't work because you have placed the headers in the base route i.e /.
You must check the headers before resolving the route. In your case route is already resolved and then you are applying the cors headers.
Use this:
app.use('/', cors(corsOptions)); or app.use(cors(corsOptions));
app.post('/', function (req, res) {
console.dir(req.body, {depth: null});
res.send('a');
});
Applying cors in app.use will add the headers. After that path will be resolved and it won't throw the error
The error message says:
Response to preflight request
The preflight is an OPTIONS request sent to ask permission to make the actual request.
Your handler only accepts POST requests, so the OPTIONS request doesn't have the required headers on it.
The documentation specifically covers preflight requests:
app.options('/', cors(corsOptions));

Node Express Cors issue

I cant figure why the cors express middleware wont work. cors, express, and ejs are all saved in package.json. The app works fine if I add corsanywhere proxy on the front end but id like to work around this on the server side. any help much appreciated I've been stuck on this.
the api is in the get View/index path
the error is:
Access to fetch at 'https://api.darksky.net/forecast/' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
const express = require('express');
const app = express();
const ejs = require('ejs');
const cors = require('cors');
const PORT = process.env.PORT || 3000;
// app.use((req, res, next) => {
// res.header('Access-Control-Allow-Origin', '*')
// res.header('Access-Control-Allow-Headers', 'Origin', 'X-Requested-With')
// next();
// });
app.use(cors());
app.use(express.static(__dirname + '/Public'));
app.set('view engine', 'ejs');
app.get('/', cors(), (req, res) => {
res.render(__dirname + '/Views/index')
});
app.listen(PORT, () => {
console.log(`server is listening on ${PORT}`)
});
client side:
it works with the ${proxy} in there but id like to get rid of that
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(position => {
long = position.coords.longitude;
lat = position.coords.latitude;
var proxy = 'https://cors-anywhere.herokuapp.com/'
var api = `${proxy}https://api.darksky.net/forecast/042750f3abefefdfe2c9d43cf33ce576/${lat},${long}`;
fetch(api)
.then(response => {
return response.json();
})
.then(data => {
let {temperature, summary, icon,} = data.currently;
temperatureDegree.textContent = Math.floor(temperature);
temperatureDescription.textContent = summary;
locationTimezone.textContent = data.timezone;
setIcons(icon, document.querySelector('.icon'
w
``````
So, if you're trying to access some other service https://api.darksky.net/forecast/ (that you don't control) from your web page, then there is nothing you can do to make CORs work for that. It's up to the api.darksky.net server to decide if CORs is allowed or not. You can't change that.
You could make a request from your web page to your server to ask it to get some data from api.darksky.net for you and then return it back to your webpage (working as a simple proxy). Your server is not subject to any CORs limitations when accessing api.darksky.net. Only browsers are limited by CORs.
And, as you've found, you can also use a proxy service that enables CORs and fetches data for you.
Let's suppose you want to proxy the parts of the darksky API, you could do something simple like this:
const express = require('express');
const app = express();
const request = require('request');
const apiRouter = express.Router();
// maps /api/forecast/whatever to http://api.darksky.net/forecast/developerKey/whatever
// and pipes the response back
const apiKey = "yourAPIKeyHere";
apiRouter.get("/*", (req, res, next) => {
// parse out action and params
// from an incoming URL of /api/forecast/42.3601,-71.0589
// the /api will be the root of the router (so not in the URL here)
// "forecast" will be the action
// "42.3601,-71.0589" will be the params
let parts = req.path.slice(1).split("/"); // split into path segments, skipping leading /
let action = parts[0]; // take first path segment as the action
let params = parts.slice(1).join("/"); // take everything else for params
request({
uri: `https://api.darksky.net/${action}/${apiKey}/${params}`,
method: "get"
}).pipe(res);
});
app.use("/api", apiRouter);
app.listen(80);
Now, when you send this server, this request:
/api/forecast/42.3601,-71.0589
it will request:
https://api.darksky.net/forecast/yourAPIKeyHere/42.3601,-71.0589
and pipe the result back to the caller. I ran this test app and it worked for me. While I didn't see anything other than forecast URLs in the darksky.net API, it would work for anything of the format /api/someAction/someParams.
Note, you probably do NOT want to enable CORS on your server because you don't want other people's web pages to be able to use your proxy. And, since you're just sending requests to your own server now, you don't need CORS to be able to do that.

Firefox NodeJS Content Security Policy (“default-src”) Error

Just upgraded to latest FF, and ALL of my backend dev is now broken.
Code example:
server.js
'use strict'
// dependencies
const bodyParser = require('body-parser')
const cors = require('cors')
const express = require('express')
// local definitions
const port = process.env.PORT || 4201
const bugsAPI = require('./bugs.api.js')
const app = express()
// Middleware
app.use(cors())
app.options('*',cors())
var allowCrossDomain = function(req,res,next) {
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE')
res.header('Access-Control-Allow-Headers', 'Content-Type')
next();
}
app.use(allowCrossDomain)
app.use(bodyParser.json())
app.use('/api/bugs', bugsAPI)
app.listen(port, () => console.log(`Server started on port ${port}`))
bugs.api.js
const router = require('express').Router()
const mongodb = require('mongodb')
const config = require('./mongo.config.json')
// load current bugList on first request
router.get('/', async (req, res) => {
const bugList = await loadBugsCollection()
res.send(await bugList.find({}).toArray())
})
// Get list of bugs
async function loadBugsCollection() {
const client = await mongodb.MongoClient.connect(
config.mongo_hook,
{
useNewUrlParser: true,
useUnifiedTopology: true
}
)
return client.db(config.db).collection('tickets')
}
module.exports = router
the following solutions have NOT worked:
Loading of a resource blocked by Content Security Policy
How to fix 'Content Security Policy: The page’s settings blocked the loading of a resource at http://localhost:8080/favicon.ico (“default-src”).'
https://lollyrock.com/posts/content-security-policy/
Helmet CSP not working correctly?
How to configure CSP-headers with express/node.js?
https://github.com/nextcloud/server/issues/12724
how to correct issue with nodejs with react app not loading content properly related to Content Security Policy
Call to function() blocked by CSP even after adding 'unsafe-eval'
https://github.com/helmetjs/helmet
Make Angular working with restrictive Content Security Policy (CSP)
Content security policy blocking remote CSS background image
Content Security Policy "data" not working for base64 Images in Chrome 28
It all worked last week. Super frustrated with this breaking change; please help!!

HTTP POST Firebase Cloud Function "Access-Control-Allow-Origin" error

I try to make HTTP POST request but I get this error
(everything is ok when I use same function on my angularjs project using __$http__) I searched similar questions here but I think I am missing a basic point on my JS request code.
Access to XMLHttpRequest at 'https://us-central1-MYAPP.cloudfunctions.net/app/MYURL' from origin has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Firebase side:
const functions = require('firebase-functions');
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors({ origin: true }));
app.post('/MYURL', (req, res) => {
// my function goes here
var clientKey = req.body.clientKey;
return res.status(200).send(clientKey);
});
exports.app = functions.https.onRequest(app);
My request code:
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
console.log(this.responseText);
}
};
xhttp.open("POST", "https://us-central1-MYAPP.cloudfunctions.net/app/MYURL", true);
xhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhttp.setRequestHeader("Access-Control-Allow-Origin", "*");
xhttp.send("clientKey=XXXXX");
Since it has been a couple of days after my question, I want to share the result here. I contacted to Firebase Support and got replied that everything should be ok with my code. I know it is funny but it works without any CORS error right now. The fact is that I really did not change anything.

Resources