5

I'm trying to restrict the origin of CORS requests to one specific domain per route using the express.js CORS package like so:

const express = require('express');
const cors = require('cors');

const port = process.env.PORT || 3000;

let app = express();

app.get('/', cors({origin: 'http://example.com'}), (req, res, next) => {
  res.sendStatus(200);
});

app.post('/', cors({origin: 'http://whatever.com'}) (req, res, next) => {
  res.sendStatus(200);
});

app.listen(port, () => {
  console.log(`Started on port ${port}`);
});

This doesn't seem to have any effect, however, as I'm able to GET and POST from any domain. I then tried instead to restrict all routes to one single origin using the following, but met the same results:

app.use(cors({origin: 'http://example.com'}));

I'm experiencing this both in my dev environment on localhost and my production environment on Heroku. Any idea what I'm missing?

dougmacklin
  • 2,560
  • 10
  • 42
  • 69
  • https://stackoverflow.com/questions/11001817/allow-cors-rest-request-to-a-express-node-js-application-on-heroku?rq=1 allow access control should be set to site from where u want to accept the request i think – Rico Mar 23 '17 at 01:03
  • @Rico what should I be doing to only allow `POST` requests to come from a certain domain, for example? – dougmacklin Mar 23 '17 at 01:10
  • res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); << keep only post here – Rico Mar 23 '17 at 01:13
  • that will still allow any origin to POST. I'm not concerned with the method as much as the origin – dougmacklin Mar 23 '17 at 01:15
  • res.header('Access-Control-Allow-Origin', 'http:/ricoGotSwag.com'); res.header('Access-Control-Allow-Methods', 'POST'); << should only allow post requests from ricoGotSwag.com << i used one / in the url cos if i use 2 then it gets converted to a link – Rico Mar 23 '17 at 01:16
  • https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers << all about http headers – Rico Mar 23 '17 at 01:17
  • hm I tried that as well, and that's supposed to do the same thing as using this express CORS package – dougmacklin Mar 23 '17 at 01:19
  • see this answer (and compare to the one above it): http://stackoverflow.com/a/21622564/1179207 – dougmacklin Mar 23 '17 at 01:21
  • What `Access-Control-Allow-Origin` value is the server sending in responses? To test, you can emulate a browser by using Postman or curl to send an `Origin` header with whatever value you want to test: `curl -i -H "Origin: https://some-not-allowed-origin" https://your-express-site` – sideshowbarker Mar 23 '17 at 01:30
  • so in the accepted answer they say to move app.use(cors({origin: 'http://example.com'})); to top in configure method – Rico Mar 23 '17 at 01:31
  • @sideshowbarker doesnt dev tools in chrome allow to see the headers of the requets sent under network tab? – Rico Mar 23 '17 at 01:43
  • @sideshowbarker using that curl command (as well as Postman) returns Access-Control-Allow-Origin → http://example.com, but the request returns a successful 200 code nonetheless and my server processes it – dougmacklin Mar 23 '17 at 01:46
  • @Rico yes when I used app.use(cors({...}) as described in the question it was at the top – dougmacklin Mar 23 '17 at 01:47
  • ok, try this code, i will post it in answer to make it look pretty – Rico Mar 23 '17 at 01:57

1 Answers1

5

If your server is sending an Access-Control-Allow-Origin: http://example.com response header, then you actually already have it configured correctly.

It’s expected behavior for the server to return a 200 response no matter what origin you make the request from—even for those from an origin other than the configured http://example.com

The CORS settings don’t cause the server to block requests from any clients.

Instead, if the server responds with Access-Control-Allow-Origin: http://example.com to a client request from JavaScript code in a web app that’s not running at http://example.com, then the browser blocks that JavaScript code from being able to access the response.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS gives more details.

Basically the way it works is that from the server side, no behavior changes other than the difference in what response headers it sends. So the server will receive the request just as it otherwise would, and will send the response just as it otherwise would.

And then the browser will receive the response just as it otherwise would. You will be able to see the response in your browser devtools and examine it there. But that does not mean the browser will expose the response to your client-side JavaScript code.

Instead, the browser checks the value of the Access-Control-Allow-Origin response header from the server and will only expose the response cross-origin to your origin if the server says it should be allowed to: Your browser checks the value of the Access-Control-Allow-Origin against your actual origin, and if it either matches exactly or the value is * to allow any origin, only then does the browser allow your client-side JavaScript code to access the response.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
  • ah ok I see where I got confused. so is there a recommended way for my server to check the origin of requests and act accordingly based on that? – dougmacklin Mar 23 '17 at 02:14
  • 2
    var ref = req.headers.referer; //req.headers.origin; if(ref==something) { do this } else { do that } – Rico Mar 23 '17 at 02:20
  • 1
    The answer to that question depends on what you mean by “act accordingly” but regardless, that seems like something you probably want to post separately as a different question from this one. It seems like you have an answer to the particular question you posted here—I mean, as far as the explanation for why you’re seeing the behavior you’re seeing and whether your express CORS configuration is working as expected (it is) or if you’ve made some mistake in the config (you haven’t) or it’s broken in some way (it’s not). – sideshowbarker Mar 23 '17 at 02:20