I am using the node-cors module in an app. I've followed some of their examples to make a cors request.
I have a route that I'd like to dynamically add cors options for:
var cors = require('cors'),
user = require('../models/user');
router.get('/route', cors(corsOptions), function(req, res) {...}
This works (this comes straight from one of the examples):
var whitelist = ['http://example1.com', 'http://example2.com'];
var corsOptionsDelegate = function(req, callback){
var corsOptions;
if(whitelist.indexOf(req.header('Origin')) !== -1){
corsOptions = { origin: true, credentials: true }; // reflect (enable) the requested origin in the CORS response
}else{
corsOptions = { origin: false }; // disable CORS for this request
}
callback(null, corsOptions); // callback expects two parameters: error and options
};
This, however, doesn't work and I'm not sure what is wrong:
var corsOptions = function(req, callback){
user.findOne({
url: req.header('Origin')
},function(err,match){
var options;
if(!empty(match)){
options = {
origin:true,
credentials: true
};
}else{
options = {
origin: false,
credentials: false
};
}
callback(null, options);
});
};
Is this an issue with the module, or something I've implemented wrong?
You need to import this:
const cors = require('cors')({origin: true}); instead of const cors = require('cors');
Related
Since yesterday I'm trying to get the books on the google API for an exercise, I had to pass on a lot of errors and here is my final code, from this moment I can't move forward:
export async function fetchGoogle (url, options = {}) {
const headers = {Accept : 'application/json', ...options.headers}
const r = await fetch(url, {...options, headers})
if (r.ok) {
return r.json()
}
throw new Error ('Error server', {cause :r})
}
// Bypass error 200
var express = require('express')
var cors = require('cors')
var app = express()
var corsOptions = {
origin: 'http://example.com',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for only example.com.'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
Then I import this into my main script :
import { fetchGoogle } from "./api.js"
const books = await fetchGoogle ('https://www.googleapis.com/auth/books')
console.log(books)
After all these fights I get the error : Uncaught ReferenceError: require is not defined
at api.js:12:15
Thanks in advance for helping
I'm attempting to create and add a socket.io module to my vTiger 7.0 so that I can update fields in real-time to multiple users.
We are have issues with users changing fields that should be locked while our quality control is attempting to check the record. This is causes things to get approved that should not. Node.js with vTiger will be awesome add-on.
The only problem is that vTiger uses csrf-magic.js to create a token that need to be included in the header to allow CORS
I have the middleware setup in my node project to allow my vtiger to make a request
vTiger is on vtiger.example.com
The node server is on node.example.com:3010
//server code node.example.com:3010
const fs = require("fs");
const config = require("./core/config").config();
var options = {
key: fs.readFileSync(config.key),
cert: fs.readFileSync(config.cert),
ca: fs.readFileSync(config.ca),
requestCert: true,
rejectUnauthorized: false,
};
const app = require("express")();
const server = require("https").Server(options, app);
const io = require("socket.io")(server);
// Need to send io to socket module
module.exports = io;
app.use(function (req, res, next) {
var allowedOrigins = [
"https://node.example.com",
"https://vtiger.example.com"
];
var origin = req.headers.origin;
if (allowedOrigins.indexOf(origin) > -1) {
res.setHeader("Access-Control-Allow-Origin", origin);
}
res.header("Access-Control-Allow-Methods", "GET, OPTIONS");
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
res.header("Access-Control-Allow-Credentials", true);
return next();
});
io.sockets.on("connection", require("./sockets/socket.js"));
const qc = require('./models/qc_model');
app.get('/', (req,res) => {
res.json({message: 'No Access'});
})
qc.pullLeadInfo(13622196, 10730, (data) => {
console.log(data.lead.lsloa_ver_by);
});
//Start the server
server.listen(config.port, () => {
console.log("server listening on port: " + config.port);
});
\\client side vtiger.example.com
var socket = io.connect('https://node.example.com:3010');
I get this error
Access to XMLHttpRequest at 'https://node.example.com:3010/socket.io/?EIO=4&transport=polling&t=NmEEc_r' from origin 'https://vtiger.example.com' 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.
csrf-magic.js:41 GET https://node.example.com:3010/socket.io/?EIO=4&transport=polling&t=NmEEc_r net::ERR_FAILED
I cannot find any good documentation dealing with this issue. Any help would be great!
Found the information here
https://github.com/socketio/socket.io/issues/3929
// Server
io.engine.on("headers", (headers) => {
headers["Access-Control-Allow-Private-Network"] = true;
});
// Client
const socket = io({
extraHeaders: {
"Access-Control-Request-Private-Network": true
}
});
front end: localhost:3000 (react app) App.js (client) on load call api '/'
function fetch_redirect() {
fetch("http://localhost:8082")
}
function App() {
return <div className="App">{fetch_redirect()}</div>;
}
export default App;
backend: localhost:8082 (nodejs express app) send redirect to /test endpoint on client
const express = require('express')
const app = express()
const cors = require('cors');
const whitelist = ['http://localhost:3000']
const corsOptions = {
origin: function (origin, callback) {
console.log(origin, whitelist.indexOf(origin) !== -1);
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
app.use(cors(corsOptions))
app.get('/', function (req, res) {
res.redirect('http://localhost:3000/test')
})
app.listen(8082)
The main issue is on the client (react) once the API call is made, the redirect is blocked... how can I make the client react app follow this redirect to 'http://localhost:3000/test' I already have cors on my backend with an enabled whitelist of localhost:3000 to allow me to make the API call not blocked... however the redirect is now blocked from the fetch frontend!
error details:
Access to fetch at 'http://localhost:3000/test' (redirected from 'http://localhost:8082/') 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.
In order to facilitate the development and have a development environment closer to what the production environment should be (no need to decrease the security level with Access-Control-Allow-Origin), you should have a unique entry point to your frontend and backend, with a unique origin (http://localhost:3000 in your case).
To achieve that, remove all of the Access-Control-* headers, create a src/setupProxy.js file and fill it like this:
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = app => {
app.use(
"/api",
createProxyMiddleware ({
target: "http://localhost:8082",
changeOrigin: true
})
);
};
Then install the needed express middleware as a development dependency with npm install --save-dev http-proxy-middleware
Note: this feature is available with react-scripts#2.0.0 and higher.
Finally, replace all of the fetch from the frontend with relative URLs starting with /api
fetch("http://localhost:8082") becomes fetch('/api'))
Something like fetch('http://localhost:8082/some-endpoint') would become fetch('/api/some-endpoint')
For more information about this, please refer to the docs.
Try to refactor your code like this:
const express = require('express')
const app = express()
const cors = require('cors');
const whitelist = ['http://localhost:3000', 'http://localhost:8082'];
const corsOptionsDelegate = (req, callback) => {
var corsOptions;
if (whitelist.indexOf(req.header('Origin')) !== -1) {
corsOptions = { origin: true };
} else {
corsOptions = { origin: false };
}
callback(null, corsOptions);
};
const corsWithOptions = cors(corsOptionsDelegate);
app.route('/')
.options(corsWithOptions, (req, res) => { res.sendStatus(200); })
.get(cors(), (req, res)=>{
res.redirect('http://localhost:3000/test')
});
app.listen(8082)
Try using next function inside app.get:
app.get('/', function (req, res, next) {
res.redirect('http://localhost:3000/test');
next();
})
Also for your ReactJS application (I'm not sure about your implementation, CSR or SSR) you should add two things:
Webpack: proxy for passing CORS
CSR:
devServer: {
...
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
"Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
}
}
SSR: add the above header to webpackDevMiddleware options.
Route:
CSR: for running the project in the dev side use:
devServer: {
historyApiFallback:{
index:'build/index.html'
},
},
for the prod side use spa flag for running, for example for serve use serve -s ./dist or for pm2 run pm2 start ./dist --spa.
SSR: no need to add extra configuration.
try something like this instead:
whitelistedOrigins = ['http://localhost:3000'];
app.use(cors({
origin: whitelistedOrigins,
methods: ['GET', 'PATCH', 'PUT', 'POST', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
}));
you can modify the methods/allowedHeaders keys as you want...
Edit: your backend is :3000, isn't it the problem? the client can't be at 3000 at the same time.
I am using firebase cloud functions and at the first time I saw cors then set origin to true.. but in that way anyone can access to my functions, so I looked a way to allow only specific domains to access my cloud functions, I got the code from cors github page and tried it, but I get unexpectedly closed the connection after waiting and waiting.
here is my function index.js --
const functions = require('firebase-functions');
const cors = require('cors');
var whitelist = ['http://example1.com', 'http://example2.com']
var corsOptionsDelegate = function (req, callback) {
var corsOptions;
if (whitelist.indexOf(req.header('Origin')) !== -1) {
corsOptions = { origin: true } // reflect (enable) the requested origin in the CORS response
}else{
corsOptions = { origin: false } // disable CORS for this request
}
callback(null, corsOptions) // callback expects two parameters: error and options
}
exports.api = functions.https.onRequest((req, res) => {
cors(req, res, () => {
var d = new Date();
var n = d.getHours();
if (n > 8 && n < 17) {
res.status(200).send("Get started")
} else {
res.status(200).send("Closed")
}
})
});
With an HTTP triggered function on Firebase Cloud Functions the cors middleware origin parameter will be undefined, as will be the request header Origin value:
var whitelist = ['https://example1.com']
var corsOptions = {
origin: function (origin, callback) {
console.log(origin) // undefined
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
console.log(req.header('Origin')) // undefined
res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
})
unless you set the Origin header yourself when you make the request to the function. For example:
await http.get(
'https://example1.com/yourfunction',
headers: {
"Origin": "https://example2.com",
},
);
The problem is that anyone can write the above request (the Origin header can be faked), so as this post suggests a more fool-proof way to verify access is by sending something like the token that Firebase Auth generates when you sign in (or you can provide the sending party with a secret key they would need to send):
await http.get(
'https://example1.com/yourfunction',
headers: {
"Authorization": "Bearer your_api_token_here",
},
);
You would then verify that it's legit in the Cloud Function (instead of checking the potentially fake origin).
Running my third party js app, it has seen so weird when play with session on the IE .
From here no problem using Chrome, FF and Safari.
My apps has the following design:
Any client can use my third party js code.
So, this widget.js just does a call for my app node using express.
This widget.js is a IIFE where on my app get the request and create the session using the code:
app.js
var emptygif = require('emptygif');
var express = require('express');
var uuid = require('node-uuid');
var expressSession = require('express-session');
var app = express();
app.set('trust proxy', 1)
app.use(expressSession({
genid: function(req) {
return uuid.v4(); // use UUIDs for session IDs
},
secret: '1234567890QWERTY',
cookie: { expires: new Date(Date.now() + 900000) },
secure: false,
httpOnly: true
}));
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
next();
});
app.get('/widget.js', function(request, response){
response.sendfile('widget.js');
});
app.get('/ping', function(req, res) {
var msg_out = load(req);
console.log( msg_out );
emptygif.sendEmptyGif(req, res, {
'Content-Type': 'image/gif',
'Content-Length': emptygif.emptyGifBufferLength,
'Cache-Control': 'public, max-age=0' // or specify expiry to make sure it will call everytime
});
});
function load(req){
var msg = {
user_token: req.session.token_bility,
time_stamp: new Date(),
user_agent: req.headers['user-agent'],
language: req.headers["accept-language"],
referrer: req.headers['referer']
}
return msg;
}
app.listen();
widget.js
(function(window, undefined) {
var _jq;
function drawWidget() {
console.log('drawing');
}
function loadSupportingFiles(_url,callback) {
var path = 'http://myserver/' + _url;
var oImg=document.createElement("img");
oImg.setAttribute('src', path);
var body = document.getElementsByTagName('body')[0];
body.appendChild(oImg);
callback();
};
function scriptLoadHandler() {
console.log('loading pixel');
}
loadSupportingFiles('ping', function() {
scriptLoadHandler();
});
})(window);
I already have done some searching by google for this questions but still without solution.
I will share with pleajure about any hint and knowledge from how to fix this.
Pay attention:
I forgotte to say some keys informations.
The token has been generated well for all browsers (IE, Chrome, FF and Safari).
But each hint for the server generate different tokens only for IE.
The behavior shows that IE expires every request.
IIFE ref.
https://en.wikipedia.org/wiki/Immediately-invoked_function_expression
Solution
After trying some parameters options this resolved.
cookie: { maxAge: 60*10000 },
secure: false,
httpOnly: true
I changed to maxAge instead expires.
These links helped me.
How to keep session in expressjs to not expire
http://mrcoles.com/blog/cookies-max-age-vs-expires/