Enable Access-Control-Allow-Origin for multiple domains in Node.js

node.jsCors

node.js Problem Overview


I'm trying to allow CORS in node.js but the problem is that I can't set * to Access-Control-Allow-Origin if Access-Control-Allow-Credentials is set.

Also the specification said I can't do an array or comma separated value for Access-Control-Allow-Origin and the suggested method would be to do something similar to this https://stackoverflow.com/questions/1653308/access-control-allow-origin-multiple-origin-domains

But I can't seem to do this way in node.js

["http://example.com:9001", "http://example.com:5001"].map(domain => {
  res.setHeader("Access-Control-Allow-Origin", domain);
});
res.header("Access-Control-Allow-Credentials", true);

The problem here is that it's bein override by the last value in the array, so the header will be set to res.setHeader("Access-Control-Allow-Origin", "http://example.com:5001");

Error from the client browser:

> XMLHttpRequest cannot load http://example.com:9090/api/sync. The > 'Access-Control-Allow-Origin' header has a value > 'http://example.com:5001'; that is not equal to the supplied origin. > Origin 'http://example.com:9001'; is therefore not allowed access.

node.js Solutions


Solution 1 - node.js

Here is what I use in my express application to allow multiple origins

app.use((req, res, next) => {
  const allowedOrigins = ['http://127.0.0.1:8020', 'http://localhost:8020', 'http://127.0.0.1:9000', 'http://localhost:9000'];
  const origin = req.headers.origin;
  if (allowedOrigins.includes(origin)) {
       res.setHeader('Access-Control-Allow-Origin', origin);
  }
  //res.header('Access-Control-Allow-Origin', 'http://127.0.0.1:8020');
  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();
});

Solution 2 - node.js

Not sure if this is to late but I solved it by setting: res.setHeader("Access-Control-Allow-Origin", req.headers.origin);

This will simply allow every connection as the headers.origin will be sent with every query.

You may want to write a function to check if the req.headers.origin is a whitelisted domain (from a hardcoded array) and the simply return this domain if it exists in the array.

Solution 3 - node.js

Check your whitelist against what your req.headers.origin e.g.

var origins = ['a.com', 'b.com', 'c.com', 'boobies.com'];
for(var i=0;i<origins.length;i++){
    var origin = origins[i];
    if(req.headers.origin.indexOf(origin) > -1){ 
         res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
         return;
    }
    // else, tough cookies. 
}

Enjoy.

Solution 4 - node.js

Here's a simple middleware function to serve up the correct CORS header from a whitelist. Setting this near the top of your express app will allow all your routes to set the proper header from the whitelist before serving up content.

app.use(function(req, res, next){
  var whitelist = ['localhost:4000', 'localhost:3000', 'anydomain.com']
  var host = req.get('host');

  whitelist.forEach(function(val, key){
    if (host.indexOf(val) > -1){
      res.setHeader('Access-Control-Allow-Origin', host);
    }
  })

  next();
});

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
QuestionAliView Question on Stackoverflow
Solution 1 - node.jschankView Answer on Stackoverflow
Solution 2 - node.jsMattView Answer on Stackoverflow
Solution 3 - node.jsRoss The BossView Answer on Stackoverflow
Solution 4 - node.jsAlan L.View Answer on Stackoverflow