Lesson Sunday

We don't talk about web application security much at Epicodus because it's beyond the scope of what we teach. However, there is one important topic we need to cover briefly now that we are working with API calls.

Same-Origin Policy

Browsers use same-origin policy (SOP) to prevent cross scripting attacks. A cross scripting attack is when a malicious user attempts to access another site via the browser. This generally involves injecting malicious scripts into a web application in an attempt to gain access, get data, or sabotage a site.

Same-origin policy means that a request can only be made from one URL to another if the receiver and the sender have the same protocol, host, and port.

Here's a quick example:

  • https://thisisthehost.com/somepage

In the URL above, https is the protocol and thisisthehost.com is the host. There is no port, and generally there won't be when we are navigating between pages, but a port would look something like this :80 and would come right after the host. We do often use ports with development servers so they can potentially be relevant in development.

Let's say that the following URL wants to make a request of the URL above:

  • https://thisisthehost.com/someotherpage

That would be entirely fine. The protocol and host are the same. The only thing different is the path, which is someotherpage instead of somepage.

How about the following URL?

  • http://somebodysuspicious.com

Well, the host name should give it away, but this is a different origin for two reasons. There's a different protocol (http instead of https) and there's a different host: somebodysuspicious.com. Because of SOP, a browser will not allow this URL to make a request to https://thisisthehost.com/somepage. Nor would the browser allow a request from `http://thisisthehost.com/someotherpage - even though the host name is the same, the protocol is different.

So why is this important when it comes to making API calls?

Well, our applicatons are entirely client-side. All the code we are running is running from the browser. We are requesting data in the form of JSON, not HTTP, but we are still doing so via a client. That means that SOP applies to our applications.

But wait a minute... how have we been able to make API calls to the OpenWeatherAPI then? How about other APIs we are working with like Giphy?

Well, these APIs have enabled a feature called cross-origin resource sharing or CORS for short. The name is pretty self-explanatory. It's a mechanism that allows resources to be shared across different origins.

Cross-Origin Resource Sharing

It's not really necessary to know the ins and outs of how cross-origin resource sharing works, but on the most basic level, it means attaching a few extra headers to requests and responses. That all happens behind the scenes so we don't need to worry about it.

What matters for us is that the APIs we work with must have CORS enabled if we want to work with them. If an API doesn't have CORS, we can't make API calls from a browser application.

For that reason, if you want to build a client-side application that makes API calls, you need to do some research first and make sure that CORS is allowed. It's not enough to make sure an API call works from Postman. In fact, that doesn't tell us anything about whether it works from the browser! Postman isn't making calls from the browser so the rules of SOP don't apply.

If you try to make a request from the browser to an API call that doesn't allow CORS, you'll get the following error in the console:

Access to fetch at 'https://othersite.com' from origin 'https://mysite.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Note that the names of the sites will be different depending on the URL you are trying to access and the one you are working with.

Working with APIs That Don't Allow CORS

Let's say you really want to work with an API that doesn't allow CORS. Is there any way around this restriction? Well, there are several options:

  • Make the API call server-side instead of client-side. If you are continuing on to Ruby/Rails or C#/.NET, you'll learn how to make API calls server-side. Wait until then to work with an API that doesn't allow CORS.
  • Build a proxy. This is well beyond the scope of the course and we don't recommend it unless you want a challenge. But you can use Node or another option to build a proxy server to allow requests to servers that don't allow CORS. This option is only listed to demonstrate that it's hard to do a workaround the right way!
  • Use a Chrome extension to alter the header. Finally, there are several Chrome extensions you can use to work around CORS including the Moesif Origin & CORS Changer extension or Allow CORS: Access-Control-Allow-Origin extension. They work by changing the header on your requests. They are easy to install and work well, but only on the local machine where the Chrome extension is installed. So while they will work fine for a learning project, they aren't good solutions for anything you might eventually want to deploy - or for a portfolio project you'd want to share or send to a potential employer. While you could technically add instructions for installing the extension in your README, that's just not going to look very professional.

So while you are welcome to use one of these extensions, just keep that fact in mind. We are still early in the program so you may not plan to turn learning projects into portfolio projects. That being said, we still recommend you pick APIs that allow CORS.

Lesson 19 of 26
Last updated October 12, 2021