Socket.io + Node.js Cross-Origin Request Blocked

node.jsSocketssocket.ioCors

node.js Problem Overview


I'm using node and socket.io to write a chat application. It works fine on Chrome but mozilla gives an error to enable the Cross-Origin Requests.

> Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://waleedahmad.kd.io:3000/socket.io/?EIO=2&transport=polling&t=1401964309289-2&sid=1OyDavRDf4WErI-VAAAI. This can be fixed by moving the resource to the same domain or enabling CORS.

Here's my code to start node server.

var express = require('express'),
    app = express(), 
    server = require('http').createServer(app),
    io = require('socket.io').listen(server),
    path = require('path');
server.listen(3000);

app.get('/', function(req, res) {
    res.sendfile(__dirname + '/public/index.html');
});

On the client side.

var socket = io.connect('//waleedahmad.kd.io:3000/');

Script tag on HTML page.

<script type="text/javascript" src="//waleedahmad.kd.io:3000/socket.io/socket.io.js"></script>

I'm also using .htaccess file in the app root directory. (waleedahmad.kd.io/node).

Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"

node.js Solutions


Solution 1 - node.js

Simple Server-Side Fix

ā— DO NOT USE "socketio" package... use "socket.io" instead. "socketio" is out of date. Some users seem to be using the wrong package.

ā— SECURITY WARNING: Setting origin * opens up the ability for phishing sites to imitate the look and feel of your site and then have it work just the same while grifting user info. If you set the origin, you can make their job harder, not easier. Also looking into using a CSRF token as well would be a great idea.

socket.io v3

docs: https://socket.io/docs/v3/handling-cors/

cors options: https://www.npmjs.com/package/cors

const io = require('socket.io')(server, {
  cors: {
    origin: '*',
  }
});

socket.io < v3

const io = require('socket.io')(server, { origins: '*:*'});

or

io.set('origins', '*:*');

or

io.origins('*:*') // for latest version

* alone doesn't work which took me down rabbit holes.

Solution 2 - node.js

I am using v2.1.0 and none of the above answers worked for me. This did though:

import express from "express";
import http from "http";

const app = express();
const server = http.createServer(app);

const sio = require("socket.io")(server, {
    handlePreflightRequest: (req, res) => {
	    const headers = {
		    "Access-Control-Allow-Headers": "Content-Type, Authorization",
		    "Access-Control-Allow-Origin": req.headers.origin, //or the specific origin you want to give access to,
		    "Access-Control-Allow-Credentials": true
	    };
	    res.writeHead(200, headers);
	    res.end();
    }
});

sio.on("connection", () => {
    console.log("Connected!");
});

server.listen(3000);

Solution 3 - node.js

You can try to set origins option on the server side to allow cross-origin requests:

io.set('origins', 'http://yourdomain.com:80');

Here http://yourdomain.com:80 is the origin you want to allow requests from.

You can read more about origins format here

Solution 4 - node.js

For anyone looking here for new Socket.io (3.x) the migration documents are fairly helpful.

In particular this snippet:

const io = require("socket.io")(httpServer, {
  cors: {
    origin: "https://example.com",
    methods: ["GET", "POST"],
    allowedHeaders: ["my-custom-header"],
    credentials: true
  }
});

Solution 5 - node.js

If you are getting io.set not a function or io.origins not a function, you can try such notation:

import express from 'express';
import { Server } from 'socket.io';
const app = express();
const server = app.listen(3000);
const io = new Server(server, { cors: { origin: '*' } });

Solution 6 - node.js

I tried above and nothing worked for me. Following code is from socket.io documentation and it worked.

io.origins((origin, callback) => {
  if (origin !== 'https://foo.example.com') {
      return callback('origin not allowed', false);
  }
  callback(null, true);
});

Solution 7 - node.js

I just wanted to say that after trying a bunch of things, what fixed my CORS problem was simply using an older version of socket.io (version 2.2.0). My package.json file now looks like this:

{
  "name": "current-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "devStart": "nodemon server.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "socket.io": "^2.2.0"
  },
  "devDependencies": {
    "nodemon": "^1.19.0"
  }
}


If you execute npm install with this, you may find that the CORS problem goes away when trying to use socket.io. At least it worked for me.

Solution 8 - node.js

In my case, I'm using an HTTP server and socket.io

Error:

var http = require('http').Server(app);
var io = require('socket.io')(http);

Solution:

var http = require('http').Server(app);
var io = require('socket.io')(http,  { cors: { origin: '*' } });

Solution 9 - node.js

After read a lot of subjetcs on StakOverflow and other forums, I found the working solution for me. This solution is for working without Express.

here are the prerequisites.


SERVER SIDE

// DEPENDENCIES
var fs 		 = require('fs'),
	winston  = require('winston'),
	path 	 = require('path');


// LOGS
const logger = winston.createLogger({
    level	  : 'info',
    format	  : winston.format.json(),
    transports: [
        new winston.transports.Console({ level: 'debug' }),
        new winston.transports.File({ filename: 'err.log', level: 'err' }),
        new winston.transports.File({ filename: 'combined.log' })
    ]
});


// CONSTANTS
const Port          = 9000,
      certsPath     = '/etc/letsencrypt/live/my.domain.com/';


// STARTING HTTPS SERVER 
var server = require('https').createServer({
	key: 				fs.readFileSync(certsPath + 'privkey.pem'), 
	cert: 				fs.readFileSync(certsPath + 'cert.pem'), 
	ca: 				fs.readFileSync(certsPath + 'chain.pem'), 
	requestCert: 		false, 
	rejectUnauthorized: false 
},
(req, res) => {
	
	var filePath = '.' + req.url;
	logger.info('FILE ASKED : ' + filePath);
    
    // Default page for visitor calling directly URL
    if (filePath == './')
        filePath = './index.html';
    
    var extname = path.extname(filePath);
    var contentType = 'text/html';
	
    switch (extname) {
        case '.js':
            contentType = 'text/javascript';
            break;
        case '.css':
            contentType = 'text/css';
            break;
        case '.json':
            contentType = 'application/json';
            break;
        case '.png':
            contentType = 'image/png';
            break;      
        case '.jpg':
            contentType = 'image/jpg';
            break;
        case '.wav':
            contentType = 'audio/wav';
            break;
    }
	
	var headers = {
		'Access-Control-Allow-Origin': '*',
		'Access-Control-Allow-Methods': 'OPTIONS, POST, GET',
		'Access-Control-Max-Age': 2592000, // 30 days
		'Content-Type': contentType
	};
	
    fs.readFile(filePath, function(err, content) {
        if (err) {
            if(err.code == 'ENOENT'){
                fs.readFile('./errpages/404.html', function(err, content) {
                    res.writeHead(404, headers);
                    res.end(content, 'utf-8');
				});
            }
            else {
				fs.readFile('./errpages/500.html', function(err, content) {
                    res.writeHead(500, headers);
                    res.end(content, 'utf-8');
				});
            }
        }
        else {
            res.writeHead(200, headers);
            res.end(content, 'utf-8');
        }
    });
	
	if (req.method === 'OPTIONS') {
		res.writeHead(204, headers);
		res.end();
	}
	
}).listen(port); 


//OPENING SOCKET
var io = require('socket.io')(server).on('connection', function(s) {
    
    logger.info("SERVER > Socket opened from client");
    
    //... your code here
    
});

CLIENT SIDE

<script src="https://my.domain.com:port/js/socket.io.js"></script>
<script>
    $(document).ready(function() {
        
        $.socket = io.connect('https://my.domain.com:port', {
            secure: true // for SSL
        });
        
        //... your code here
        
    });
</script>

Solution 10 - node.js

client:

const socket = io('https://sms-server.cedrick1227.repl.co/', { });

server:

const io = new socket.Server(server, { cors: { origin: '*' } });

it works like a charm for me.

Solution 11 - node.js

This could be a certification issue with Firefox, not necessarily anything wrong with your CORS. https://stackoverflow.com/questions/24371734/firefox-cors-request-giving-cross-origin-request-blocked-despite-headers

I was running into the same exact issue with Socketio and Nodejs throwing CORS error in Firefox. I had Certs for *.myNodeSite.com, but I was referencing the LAN IP address 192.168.1.10 for Nodejs. (WAN IP address might throw the same error as well.) Since the Cert didn't match the IP address reference, Firefox threw that error.

Solution 12 - node.js

Alright I had some issues getting this to work using a self signed cert for testing so I am going to copy my setup that worked for me. If your not using a self signed cert you probably wont have these issues, hopefully!

To start off depending on your browser Firefox or Chrome you may have different issues and I'll explain in a minute.

First the Setup:

Client

// May need to load the client script from a Absolute Path
<script src="https://www.YOURDOMAIN.com/node/node_modules/socket.io-client/dist/socket.io.js"></script>
<script>
var options = {
          rememberUpgrade:true,
          transports: ['websocket'],
          secure:true, 
          rejectUnauthorized: false
              }
var socket = io.connect('https://www.YOURDOMAIN.com:PORT', options);

// Rest of your code here
</script>

Server

var fs = require('fs');

var options = {
  key: fs.readFileSync('/path/to/your/file.pem'),
  cert: fs.readFileSync('/path/to/your/file.crt'),
  
};
var origins = 'https://www.YOURDOMAIN.com:*';
var app = require('https').createServer(options,function(req,res){
   
	// Set CORS headers
	res.setHeader('Access-Control-Allow-Origin', 'https://www.YOURDOMAIN.com:*');
	res.setHeader('Access-Control-Request-Method', '*');
	res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
	res.setHeader('Access-Control-Allow-Headers', '*');
	if ( req.method === 'OPTIONS' || req.method === 'GET' ) {
		res.writeHead(200);
		res.end();
		return;
            }
 
});

var io = require('socket.io')(app);

app.listen(PORT);

For development the options used on the client side are ok in production you would want the option:

 rejectUnauthorized: false

You would more than likely want set to "true"

Next thing is if its a self signed cert you will need to vist your server in a separate page/tab and accept the cert or import it into your browser.

For Firefox I kept getting the error

MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT

The solution for me was to add the following options and accepting the cert in a different page/tab.

{ 
rejectUnauthorized: false
} 

In Chrome I had to open another page and accept the cert but after that everything worked fine with out having to add any options.

Hope this helps.

References:

https://github.com/theturtle32/WebSocket-Node/issues/259

https://github.com/socketio/engine.io-client#methods

Solution 13 - node.js

I am facing problem while making an chat app using socket.io and node.js & React. Also this issue is not spacefic to Firefox browser, i face same issue in Edge & Chrome also.

> "Cross-Origin request is blocked and it is used by some other resources..."

Then i download cors in project directory and put it in the server file index.js as below: To download simply type command using node.js :

> npm install cors

const cors = require('cors');
app.use(cors());

This will allow CORS to used by different resources in the files and allow cross origin request in the browser.

Solution 14 - node.js

Here is the solution from the official documentation:

> Since Socket.IO v3, you need to explicitly enable Cross-Origin Resource Sharing (CORS).

const io = require("socket.io")(httpServer, {cors: {
origin: "https://example.com", // or "*"
methods: ["GET", "POST"]}});

Solution 15 - node.js

Take a look at this: Complete Example

Server:

let exp = require('express');
let app = exp();

//UPDATE: this is seems to be deprecated
//let io = require('socket.io').listen(app.listen(9009));
//New Syntax:
const io = require('socket.io')(app.listen(9009));

app.all('/', function (request, response, next) {
    response.header("Access-Control-Allow-Origin", "*");
    response.header("Access-Control-Allow-Headers", "X-Requested-With");
    next();
});

Client:

<!--LOAD THIS SCRIPT FROM SOMEWHERE-->
<script src="http://127.0.0.1:9009/socket.io/socket.io.js"></script>
<script>
    var socket = io("127.0.0.1:9009/", {
        "force new connection": true,
        "reconnectionAttempts": "Infinity", 
        "timeout": 10001, 
        "transports": ["websocket"]
        }
    );
</script>

I remember this from the combination of stackoverflow answers many days ago; but I could not find the main links to mention them

Solution 16 - node.js

i simply updated the version of socket.io from 2.x.x to 4.1.2 for backend and did the same ie. updated the version of socket.io-client at frontend from 2.x.x to 4.1.2 ....And it worked

Solution 17 - node.js

So, basically in v2, the Socket.IO server automatically added the necessary headers to allow Cross-Origin Resource Sharing (CORS) therefor there was no problem for connection between client and server. But this behavior, while convenient, was not great in terms of security, because it meant that all domains were allowed to reach your Socket.IO server.

In v3 and above versions the CORS is disabled by default. Therefor you need to explicitly enable them on your server side script.

Example of my code:

In v2 of socket.io the server script looked like :

const io = require('socket.io')(8000);

But in v3 and above versions this code becomes to :

const io = require('socket.io')(8000, {
    cors: {
            origin: ['http://localhost:5500'],
     },
  });

// Remember by setting cors you allow you client to communicate with the socket server

// In this case 8000 is my port on which my socket connection is running and 5500 is my port where my client files are hosted.

// Socket connection runs on a different port and your client files on different

// Also you need to install socket.io-client where you have installed your socket.io modules

For more clarification I'm adding my files

This is my HTML File :

<!DOCTYPE html>
  <html lang="en">
   <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="http://localhost:8000/socket.io/socket.io.js"" content="text/javascript"></script>
    <script src="javascript/client.js"></script>
    <link rel="stylesheet" href="css/style.css">
    <title>Chat App</title>
   </head>
   <body>
   </body>
  </html>

Here is my javascript/client.js

const socket = io('http://localhost:8000/');

And this is server/server.js

const io = require('socket.io')(8000, {
  cors: {
   origin: ['http://localhost:5500'],
   },
 });

io.on('connection', socket =>{
  console.log(socket.id);
 });

// If you still can't get it more detailed information can be seen on https://socket.io/docs/v4/migrating-from-2-x-to-3-0/#CORS-handling

// Also a video from which i got this solution https://youtu.be/ZKEqqIO7n-k

Solution 18 - node.js

For those using socket.io >= v4.4.0

Because I wanted needed the CORS option only for local development, nothing worked here for me.

The solution that I implemented, backend-side :

    const io = require("socket.io")(server, {
		path: '/api/socket.io',
	});

	if (process.env.NODE_ENV === 'development') {
		io.engine.on('initial_headers', (headers, req) => {
			headers['Access-Control-Allow-Origin'] = 'http://localhost:3000';
			headers['Access-Control-Allow-Credentials'] = true;
		});

		io.engine.on('headers', (headers, req) => {
			headers['Access-Control-Allow-Origin'] = 'http://localhost:3000';
			headers['Access-Control-Allow-Credentials'] = true;
		});
	}

Solution 19 - node.js

The combination that works for me is:

socketio = require('socket.io')(http, {
  origins: process.env.WEB_URL, // http(s)://...
  cors: {
    origin: process.env.WEB_URL,
    credentials: true
  }
}).listen(process.env.SOCKET_PORT) // 8899

app.set('socketio', socketio)

Solution 20 - node.js

I had the same problem and any solution worked for me.

The cause was I am using allowRequest to accept or reject the connection using a token I pass in a query parameter.

I have a typo in the query parameter name in the client side, so the connection was always rejected, but the browser complained about cors...

As soon as I fixed the typo, it started working as expected, and I don't need to use anything extra, the global express cors settings is enough.

So, if anything is working for you, and you are using allowRequest, check that this function is working properly, because the errors it throws shows up as cors errors in the browser. Unless you add there the cors headers manually when you want to reject the connection, I guess.

Solution 21 - node.js

Using same version for both socket.io and socket.io-client fixed my issue.

Solution 22 - node.js

Sometimes this issue is faced when the node server stoped. So, check if your node server working ok.

Then you can use io.set('origins', 'http://yourdomain.com:PORT_NUMBER';);

Solution 23 - node.js

I used version 2.4.0 of socket.io in easyRTC and used the following code in server_ssl.js which worked for me

io = require("socket.io")(webServer, {
  handlePreflightRequest: (req, res) => {
    res.writeHead(200, {
      "Access-Control-Allow-Origin": req.headers.origin,
      "Access-Control-Allow-Methods": "GET,POST,OPTIONS",
      "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept, Referer, User-Agent, Host, Authorization",
      "Access-Control-Allow-Credentials": true,
	  "Access-Control-Max-Age":86400
    });
    res.end();
  }
});

Solution 24 - node.js

If you get socket.io app working on Chrome, Safari and other browsers but you still encounter CORS issues in Firefox, and you are using a self-signed certificate, then the problem is that Firefox does not accept self-signed certificates by default, and you have to add an exception by going to Firefox's Preferences > Certificates > View Certificates > Add Exception.

If you don't do this, then Firefox shows the error you posted which is misleading, but deep within its Developer Tools, you will find this error: MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT. This indicates that Firefox is not accepting the certificate at all because it is self-signed.

Solution 25 - node.js

const options = {
  cors: {
    origin:
      String(process.env.ORIGINS_STRING) === "ALL"
        ? true
        : String(process.env.ORIGINS_STRING).split(","),
    methods: ["GET", "PUT", "POST", "DELETE"],
    allowedHeaders: [
      "Access-Control-Allow-Headers",
      "X-Requested-With",
      "X-Access-Token",
      "Content-Type",
      "Host",
      "Accept",
      "Connection",
      "Cache-Control",
    ],
    credentials: true,
    optionsSuccessStatus: 200,
  },
};

in .env file :

ORIGINS_STRING=ALL

or

ORIGINS_STRING=http://localhost:8080,http://localhost:8081

Solution 26 - node.js

I was working with socket.io: 4.2.x, node: 14.17.x & @hapi/hapi: 20.1.x.

After trying multiple ways as mentioned in other answers, I found that the only working solutions for these version is:

const io = require('socket.io')(server.listener, { cors: { origin: '*' } });

Please make sure you have { cors: { origin: '*' } } in the options object.

Solution 27 - node.js

I am using SocketIO with implicit http server and I am using v4.4 of socket io, I had to do it like this in the server:

const { Server } = require("socket.io");

const io = new Server(PORT, {})
io.engine.on("headers", (headers, req) => {
	headers["Access-Control-Allow-Origin"] = "http://yourdomain.com"
	headers["Access-Control-Allow-Headers"] = "origin, x-requested-with, content-type"
	headers["Access-Control-Allow-Methodsn"] = "PUT, GET, POST, DELETE, OPTIONS"
})

Solution 28 - node.js

I was also struggling with this issue until i saw Documentation says: "You can't set 'withCredentials' to true with origin: *, you need to use a specific origin:". So my code looks like this, hope is useful:

WEB CLIENT

const { io } = require("socket.io-client");
const socket = io("localhost:3000", {
  extraHeaders: {
    "my-custom-header": "abcd"
  }
});

SERVER

var express = require('express');
const app = express();
const http = require('http');
const httpServer = http.createServer(app);
const io = require("socket.io")(httpServer, {
  cors: {
    origin: '*',
    methods: ["GET", "POST"],
  }
});

Solution 29 - node.js

just simply do this in your socketio requiring:-

const io = require("socket.io")(8000, {
     cors: {
	    origin: "*",
     },
});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionWaleed AhmadView Question on Stackoverflow
Solution 1 - node.jsKing FridayView Answer on Stackoverflow
Solution 2 - node.jsKwabena BerkoView Answer on Stackoverflow
Solution 3 - node.jsOlegView Answer on Stackoverflow
Solution 4 - node.jsBrett KlassenView Answer on Stackoverflow
Solution 5 - node.jsOleksandr DanylchenkoView Answer on Stackoverflow
Solution 6 - node.jshdkView Answer on Stackoverflow
Solution 7 - node.jsDavid CarrascoView Answer on Stackoverflow
Solution 8 - node.jsKARTHIKEYAN.AView Answer on Stackoverflow
Solution 9 - node.jsMelomanView Answer on Stackoverflow
Solution 10 - node.jsSpadefaithView Answer on Stackoverflow
Solution 11 - node.jsRyan SmithView Answer on Stackoverflow
Solution 12 - node.jsKyle CootsView Answer on Stackoverflow
Solution 13 - node.jsakshay_sushirView Answer on Stackoverflow
Solution 14 - node.jsGnoporView Answer on Stackoverflow
Solution 15 - node.jsShamshirsaz.NavidView Answer on Stackoverflow
Solution 16 - node.jsVivek BhoreView Answer on Stackoverflow
Solution 17 - node.jsprajwal tulaweView Answer on Stackoverflow
Solution 18 - node.jsFR073NView Answer on Stackoverflow
Solution 19 - node.jsWayne SmallmanView Answer on Stackoverflow
Solution 20 - node.jspykissView Answer on Stackoverflow
Solution 21 - node.jsAdwaithView Answer on Stackoverflow
Solution 22 - node.jsSandeep SherpurView Answer on Stackoverflow
Solution 23 - node.jsImran RafiqueView Answer on Stackoverflow
Solution 24 - node.jstsaixingweiView Answer on Stackoverflow
Solution 25 - node.jsMahdadView Answer on Stackoverflow
Solution 26 - node.jsRajeshwarView Answer on Stackoverflow
Solution 27 - node.jssasidharView Answer on Stackoverflow
Solution 28 - node.jsOswaldo OsunaView Answer on Stackoverflow
Solution 29 - node.jsAjay jangidView Answer on Stackoverflow