AIon
AIon

Reputation: 13071

Browser not setting the origin header for cross origin requests?

I have a simple index.html file. This html is loading from localhost:3000

<body>
    <h1>Some app</h1>
    <script src="http://localhost:3005/script.js"></script>
</body>

The script.js is set to load from another origin: localhost:3005.

From my understanding, The browser should intercept the request and add the origin header to it - and make a preflight request to localhost:3005 server to check if localhost:3000 is allowed.

But i'm getting no origin. The browser doesn't seem to add the origin header. This is the server responsible for serving the script.js file (localhost:3005). I'm using the cors module.

const app = express()

const whitelist = ["http://localhost:3001"]
const corsOptions = {
    origin: function(origin, callback) {
        console.log("origin is: ", origin);      //undefined -- why is undefined??

        if (whitelist.indexOf(origin) !== -1) {
            callback(null, true)
        }
        else {
            callback(new Error('Not allowed by CORS'))
        }
    }
}

app.use(cors(corsOptions), express.static(__dirname))
app.listen(3005, () => {
    console.log("server listening on port 3005")
})

My actual goal is to white-list only localhost:3000 for asking for my script.js

And i put localhost:3001 just to test if i'm actually getting a cors error - as it should be.

But i'm not even getting the origin - what is causing this? I'm getting the same behavior in both Firefox and Chrome. Did i misunderstood this hole process? Thanks :)

EDIT: Maybe seeing the request helps

browser doesn't attach the origin header

Upvotes: 11

Views: 13204

Answers (2)

Pas
Pas

Reputation: 124

For others who may come across this question, here is a practical demonstration of Kevin Christopher Henry's accepted answer above.

This first code snippet below requests a script (a .js file with an src URL) from the domain www.w3schools.com (and automatically executes it too upon the success of request, but that's not important here). Two things to note here:

  1. This request for a script is being made to a different domain (www.w3schools.com) than where it's originating from.
  2. This runs successfully.

$.ajax({
  url: 'https://www.w3schools.com/lib/w3codecolor.js',
  dataType: "script",
  success: function(data, status) {
    console.log('Result:', status)
  },
  error: function(err, status) {
    console.log('Error:', error);
  },
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

This second code snippet below requests a URL (https://www.w3schools.com/bootstrap) to a specific route/page from the domain www.w3schools.com using XHR . This is what you would use when making requests to API endpoints. This is what CORS has jurisdiction over. Two things to note here:

  1. This request is being made to a different domain (www.w3schools.com) than where it's originating from.
  2. This fails because modern browsers restrict cross-origin HTTP requests (see more) by default. Now the only way around this is by configuring CORS on www.w3schools.com domain to accept XHR requests from outside its own domain.

$.ajax({
  url: 'https://www.w3schools.com/bootstrap',
  success: function(data, status) {
    console.log('Result:', status)
  },
  error: function(err, status) {
    console.log('Error:', err);
  },
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

The error here is ambiguous. To see the actual CORS error, open Web Developers Console and you should see something like

"Access to XMLHttpRequest at 'https://www.w3schools.com/bootstrap' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."

Now the reason why the error says "from origin 'null'" is because these code snippets are probably being run from sandboxed environments where it's not even setting the request header Origin to "https://stackoverflow.com".

However, the result would be the same if the Origin was actually set to "https://stackoverflow.com". Feel free to copy paste the above scripts into Web Developer Console and try it out.

Upvotes: 0

Kevin Christopher Henry
Kevin Christopher Henry

Reputation: 48932

I think you might be misunderstanding the purpose of CORS. It gives servers the ability to opt-in to certain kinds of requests that would otherwise be disallowed under the browser's Same Origin Policy. It doesn't provide a mechanism to disallow requests that were previously allowed.

Executing scripts from foreign origins in the src of a <script> tag has always been allowed under the Same Origin Policy, and so CORS simply doesn't apply. That's why there's no header on the request.

My actual goal is to white-list only localhost:3000 for asking for my script.js.

You can't use CORS for that. In fact, you probably can't do that at all. I would take a step back and ask why you want to do that. If you're trying to secure private data then some sort of authentication mechanism (tokens, cookies, whatever) is probably necessary.

Upvotes: 2

Related Questions