Node.JS, Socket IO: Same Origin Policy error - node.js

I am having an hard time making server and client interact.
Here is the relevant code:
var mongodb = require('mongodb');
var fs = require('fs');
var http = require('http');
var express = require('express');
var io = require('socket.io');
var cors = require('cors');
var app = express();
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8888');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
app.use(express.static('./public'));
app.get('/', function(req, res) {
res.send('/index.html')
});
var server = http.createServer(app)
io = io.listen(server);
server.listen(8000);
The website loads the io.js script with:
<script src="http://localhost:8000/socket.io/socket.io.js"></script>
If I remove the port number I get a plain not found error and undefined io.
However, I get the following error, in Chrome:
GET http://localhost/socket.io/?EIO=3&transport=polling&t=1441274392959-0
XMLHttpRequest cannot load http://localhost/socket.io/?EIO=3&transport=polling&t=1441274392959-0. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. The response had HTTP status code 404.
In Firefox:
GET XHR http://localhost/socket.io/ [HTTP/1.0 404 Not Found 2ms]
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost/socket.io/?EIO=3&transport=polling&t=1441275119628-17. (Reason: CORS header 'Access-Control-Allow-Origin' missing).
Searching for the Cross-Origin error, I tried a couple of sulutions:
The setHeader section I used in the code,
https://stackoverflow.com/a/21622564 tried on app, server and io.
Neither of them worked, and I don't understand why.
Can someone help me sort this out?
Thanks.

i thinks its because your ports are different
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8888');
and
server = server.listen(8000)

You can set the CORS header on your server like so :
var io = require('socket.io').listen( ... );
io.set("origins", "*:*");
Please note that in a production environment you should replace the wildcard with expected origins

Seems, you need change listen from socket.io to server. You add cors policy to your express listener so port must be listened by http server itself
server = require('http').Server(app);
io = require('socket.io')(server);
server = server.listen(8000)

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?

socket.io: io.origins is not a function

I'm trying to enable Cross-Origin Same Domain requests for my socket.io nodejs server, but for some reason it keeps telling me io.origins is not a function ?
var io = require('socket.io', 3000);
io.origins("*");
TypeError: io.origins is not a function
**UPDATE, The Cross-Origin Error: **
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://:3000/socket.io/?EIO=3&transport=polling&t=NMWwT1R. (Reason: CORS request did not succeed).
EDIT 2:
As for why you're getting that CORS error, it's because you haven't configured the Socket.IO cors option properly.
Now, the cors configuration for Socket.IO actually gets passed to the NPM package cors, so you need to make your cors configuration work with the cors package.
For your case, that would look like:
cors: {
// The `*` is used as the wildcard here.
origin: "*",
// Set the other options according to your needs.
// The docs are here:
// https://www.npmjs.com/package/cors#configuration-options
methods: ["GET", "POST"],
allowedHeaders: ["content-type"]
}
EDIT 1:
Now that I know you are using Socket.IO 3.0, I may be able to help you better.
Socket.IO 3.0 includes a bunch of breaking changes (see the full changelog here), so that may be why you are getting that TypeError: io.origins is not a function.
As for that CORS error, Socket.IO 3.0 removed some old options, and added some new ones for CORS management. One of the removed options was the origins property. That's why your code is not working: you aren't actually setting any CORS configurations. To set CORS configurations in Socket.IO 3.0, use the options below:
// I still use a port here, because it works, but you could use #Aryas'
// code if you wish.
const io = socketIO(3000, {
// Now, the CORS config.
// You could either use the new `cors` property...
cors: {
origin: "https://example.com",
methods: ["GET", "POST"],
allowedHeaders: ["content-type"]
},
// ...Or the old `allowRequest` function.
allowRequest: function(req, callback) {
callback(null, req.headers.referer.startsWith("https://example.com"));
}
});
Oh, and, setting CORS options in Express is not necessary; Socket.IO picks up requests that are for it automatically, before any Express handlers are called.
ORIGINAL ANSWER:
It's telling you that because your io variable is not an instance of the Socket.IO server. Instead, it's the Socket.IO server constructor. Why?
Well, you have this code:
// You are passing two parameters to `require`: "socket.io", and 3000
var io = require("socket.io", 3000);
require returns whatever is exported by the module, which, in this case, is the Socket.IO server constructor (not an instance of it). The 3000 you passed to require doesn't do anything, since require only accepts one argument.
In order to get a Socket.IO server instance, you need to do this:
// The clearer way:
// `socketIO` is the Socket.IO server constructor.
var socketIO = require("socket.io");
// `io` is the Socket.IO server instance.
var io = socketIO(3000);
// The shorter way:
// Calling the result of `require` (the Socket.IO server constructor) as a function.
var io = require("socket.io")(3000);
UPDATE 2
As you mentioned in this https://pastebin.com/1TDhWxaC code I found that you are using fire fox try this code on Chrome or other browser's i think it will work on that browser
There is bug or problem certificate or something else in in firefox you will notice this in all below cases
I suggest you to go through below questions and answers
Firefox 'Cross-Origin Request Blocked' despite headers
CORS request did not succeed on Firefox but works on Chrome
Socket.io + Node.js Cross-Origin Request Blocked
CORS Blocked with node.js and socket.io
Socket.IO: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource
//Error in Firefox client:
//Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://<MY_EXTERNAL_IP>:3000/socket.io/?EIO=3&//transport=polling&t=NMX8aWc. (Reason: CORS request did not succeed)
UPDATE 1
IN your app.js or index.js
put below code
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", '*');
res.header("Access-Control-Allow-Credentials", true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header("Access-Control-Allow-Headers", 'Origin,X-Requested-With,Content-Type,Accept,content-type,application/json');
res.header("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0");
next();
});
If you are using firefox refer to this answer : Answer on stackOverflow
And Install cors If you haven't used in your app
You can use cors npm in express.
npm install cors
Update app.js
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
ORIGINAL ANSWER
Try This maybe it could Work for you it is working fine in my app
var express = require('express');
var app = express();
var http = require('http').Server(app);
const io = require('socket.io')(http, {
origins: '*:*'
});
http.listen(port);
console.log('Server is running on port:' + port);

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

I've angular cli project that hosted in azure and I'm making API call to different domain (in Zoho creator) so I have CROS issue I tried some solutions with no luck.
The error is
"Access to XMLHttpRequest at "https://xxxxxxx" from origin "https://yyyyyy" has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."
I use expressJS as my backend and I tried to add headers but it seems not working I don't know what I'm missing
APP.JS
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const http = require('http');
const app = express();
// parse application/x-www-form-urlencoded
var cors = require('cors');
// Use this after the variable declaration
app.use(cors({origin: '*'}));
// parse application/json
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// Angular DIST output folder
app.use(express.static(path.join(__dirname, 'dist')));
// Send all other requests to the Angular app
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
// Add headers
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:5000');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
//Set Port
const port = process.env.PORT || '5000';
app.set('port', port);
const server = http.createServer(app);
server.listen(port, () => console.log(`Running on localhost:${port}`));
I don't recognize exactly what It's happening but there's something that it makes me noise.
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:5000');
This code indicate that you can only receive requests from http://localhost:5000. Are you trying to consume it from http://localhost:5000? I don't think so because the port 5000 is being used by node.js. if you want to use it, you must set Access-Control-Allow-Origin to the Server or Site where you're trying consume it from.
Example, I have a application in Angular in my machine using the port 4200, so the request header should be:
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
Or, you can use * to allow everything but It's not secure.
res.setHeader('Access-Control-Allow-Origin', '*');

Angular client enable CORS

CORS is fine on server and works as intended. I tried sending requests to my server's REST API with the angular HTTPClient and I receive a CORS error.
Why is this an error if CORS is enabled on the server? Shouldn't it be fine on the client?
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:3000/api/blah/blah (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
How can I enable CORS on this request please.....
For future refrence it was "Davids" answer that assisted me, the cors was not added before all routing.
"..... Meaning, before the route is defined."
so right after ...
var app = express();
I just use...
app.use(cors());
A little intro:
Cross-Origin Resource Sharing aka CORS is a mechanism that uses additional HTTP headers to tell browsers to give a web application running at one origin (e.g. http://localhost:3000), access to selected resources from a different origin (e.g. http://localhost:8080). In other words, a web app executes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, or port) from its own. For security reasons, browsers restrict cross-origin HTTP requests initiated from scripts.
The Access-Control-Allow-Origin header determines which origins are allowed to access server resources over CORS.
How to Fix CORS Issues?
You can do it yourself by creating an Express middleware. Here's the appropriate code snippet:
// Enable CORS for specific origins:
app.use((req, res, next) => {
// Allow multiple predefined origins
const allowedOrigins = ["https://deployed-app.com", "http://localhost:3000"];
const origin = req.headers.origin; // extract the origin from the header
if (allowedOrigins.indexOf(origin) > -1) { // if the origin is present in our array
res.setHeader("Access-Control-Allow-Origin", origin); // set the CORS header on the response
}
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next(); // move on to the next middleware
});
Alternatively, you can accept all requests,
but this option is only appropriate if you're in development or if your API is public :)
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
next();
});
Additionally, there's an Express CORS middleware and this is how you would use it:
npm install cors --save
Enable All CORS Requests:
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
});
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log(`CORS-enabled server is up on ${port}`);
});
Enable CORS for a Single Route
const express = require('express');
const cors = require('cors');
const app = express();
app.get('/products/:id', cors(), (req, res, next) => {
res.json({msg: 'This is CORS-enabled for a Single Route'})
});
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log(`CORS-enabled server is up on ${port}`);
});
Important gotcha: When it comes to Express middleware, the order is very important. So make sure CORS is enabled before any other controller/ route/ middleware which may depend on it.
You dont need to enable cors in angular, this is a server side issue. See:
https://stackoverflow.com/a/29548846/4461537

Socket.io - Origin is not allowed access

I'm having this weird problem with socket.io. I have an express app which I run on port 5000. I have configured socket.io like this:
const app = require('../index');
const http = require('http');
const server = http.Server(app);
const io = require('socket.io')(server);
io.on('connection', function (socket) {
console.log('User has connected');
socket.emit('connect', {
message: 'Hello World'
});
});
Then I import this piece of code into my index.js file like this:
const express = require('express');
const app = module.exports = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const request = require('request');
const boxRoutes = require('./routes/v1/boxRoutes');
const bidRoutes = require('./routes/v1/bidRoutes');
// use body parser so we can get info from POST and/or URL parameters
app.use(bodyParser.urlencoded({ limit: '10mb', extended: true }));
app.use(bodyParser.json({ limit: '10mb' }));
require('./services/usersClass');
// cors set up
app.use(cors());
app.use(function (req, res, next) {
console.log('Headers Middleware Called');
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'origin, x-requested-with, content-type, accept, x-xsrf-token', 'token');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Request headers you wish to expose
res.setHeader('Access-Control-Expose-Headers', false);
next();
});
// Middleware to authenticate the requests to this service
app.use(function(req, res, next) {
console.log('Auth Middleware Called');
if(!req || !req.headers['authorization']) return res.sendStatus(401);
const token = req.headers['authorization'].split(' ')[1];
request.post(
'http://localhost:4000/api/v1/users/auth',
{
headers: {
'Authorization': `Bearer ${token}`
}
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
const data = JSON.parse(body);
res.locals.user = data.user;
next();
} else {
console.log('Request has failed. Please make sure you are logged in');
res.sendStatus(401);
}
}
);
});
app.use('/api/v1/boxes/', boxRoutes);
app.use('/api/v1/bids/', bidRoutes);
// disable 'powered by'
app.disable('x-powered-by');
app.listen(5000, () => {
console.log('Trading service is running on port 5000');
});
Now, in my client code, I try to establish socket.io connection when the user logs in. Everytime I try to connect to the server, I get the following error:
Failed to load
http://localhost:5000/socket.io/?EIO=3&transport=polling&t=MA_9wXE:
Response to preflight request doesn't pass access control check: The
value of the 'Access-Control-Allow-Origin' header in the response must
not be the wildcard '*' when the request's credentials mode is
'include'. Origin 'http://localhost:3000' is therefore not allowed
access. The credentials mode of requests initiated by the
XMLHttpRequest is controlled by the withCredentials attribute.
I don't understand why the connection fails. I have configured Access-Control-Allow-Origin to my client domain but it still fails.
You can use cors npm module. It will fix your problem.
var cors = require('cors')
var app = express()
app.use(cors({origin: '*'}))
start '*' means allow every origins. You can type spesific origin too.
I've seen this problem before, but never seen it manifested as a cross origin issue. You are creating two separate http servers. One you are making your express server and the other you are making your socket.io server. The code you show only actually starts the express server and you show no code that actually starts your socket.io server.
Here's where you create these two separate servers:
const server = http.Server(app); // creates the http server you use for socket.io
app.listen(5000, () => {...}); // creates the http server you use with Express
Inside of app.listen(), it creates it's own new server and starts it. Your other server is never started (at least per the code you show here).
When you probably want to do is to make your socket.io server use the same server as your express server and then you should be able to connect just fine without any CORs issues.
If you want to use app.listen(), it will return the server object that it created and you need to use that to initialize socket.io.
If you want to use the other server, then you need to share that with your express initialization code so it can use that one.

Resources