Cross Origin Resource Sharing

Dealing with CORS (Cross-Origin Resource Sharing) in Ionic Applications



·

Almost everybody who is developing Ionic applications will at some point or another run into a fun little error that looks something like this:

No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:8100' is therefore not allowed access.

The Access-Control-Allow-Origin error you see here is the result of the browser’s implementation of CORS (Cross-Origin Resource Sharing). This is an exceedingly common error, but it is also something that is also widely misunderstood.

This is an issue I’ve seen popping up on forums more and more frequently lately (likely due to people upgrading from UIWebView to WKWebView). I wanted to write this quick guide to explain what CORS is, and how you can work with it (or sometimes, against it).

Once you understand what is going on, these errors become much less intimidating and much easier to solve.

What is CORS?

CORS stands for Cross-Origin Resource Sharing and it is a security protocol implemented by browsers that allow a server to determine what domains/origins should be allowed access to its resources.

Since an Ionic application runs inside of a browser, CORS will apply to requests that are launched from within an Ionic application.

By default, the same-origin security policy is used, which means that the browser will only allow the loading of resources from the server if the request was launched from that same origin. That means that if my application is running on coolfishieswithhats.com and I am trying to make a request to a server on dogswithfancyshoes.com it will be blocked by CORS with an error that looks something like this:

No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'https://coolfishieswithhats.com' is therefore not allowed access.

The browser will allow cross-origin requests like this to succeed, but only if the server the request is being made to explicitly allows requests from that origin (or from all origins) using an appropriate header.

If we are developing an Ionic application on a desktop, then the origin in the browser will be:

http://localhost:8100

Since our requests would be coming from the localhost origin, then any server we are trying to request resources from would need to allow that origin.

If we were using Ionic and their web view plugin to run the application on a device, then the origin would also be localhost because Ionic spins up a local web server to serve content on the device

If you are just using the standard Cordova web view then assets will be served from the file:// origin.

If you’re not too sure about what origin your application is running on it doesn’t really matter, because the Access-Control-Allow-Origin error will soon tell you if you’re wrong!

The Solution for CORS Issues

The best way to deal with CORS is to abide by the rules of the browser and implement CORS correctly. That means enabling CORS on the server you are making a request to.

The reason not enabling CORS is an issue is because the server you are making a request to is saying “No, I don’t give permission for external domains to access my resources” in the eyes of the browser. The solution then is to modify your server so that it instead says “Yes, external domains are free to use my resources” or “Yes, it is OK for coolfishieswithhats.com to access my resources”.

Exactly how you enable CORS depends on your server. In general, you need to add a header to the server response that looks like this:

Access-Control-Allow-Origin: *

NOTE: This will allow access to all origins, but you can also just allow specific origins if you want.

But, the way in which you add headers will depend on what server-side technologies you are using. If you are not sure how to add the header, I would recommend taking a look at enable-cors.org. This is a fantastic resource that contains just about everything you would ever need to know about CORS, and also has a lot of example implementations for various server-side technologies.

Ultimately, the best way to deal with CORS is to add the appropriate header to the response from the server. However, you don’t always necessarily have the ability to add this header, perhaps for the following reasons:

  1. You are building a solution for an existing server that a client won’t give you permission to change
  2. You are using a service that does not allow you to modify the CORS settings
  3. You are attempting to pull in resources from somebody else’s server that does not have CORS enabled

As a first step to solving these, I think the “best” solutions are:

  1. Convince the client to make this change
  2. Use a different service that provides the ability to configure CORS correctly
  3. Consider whether you are using this server in an intended manner, and if you are, perhaps suggest that they enable CORS

However, we live in the real world and often we do end up in situations where we can’t always use the “best” solution, which brings me to potential workarounds…

Working Around CORS Issues

As I mentioned, CORS is implemented by browsers, and fortunately for us, there are some ways we can work around that. Again, I’d like to stress that these options should only be used if necessary – the fewer workarounds you use to build your app, the better.

I will list these workarounds in my order of preference from best to worst.

1. Proxy requests through an additional server

Since CORS is implemented by browsers, it won’t stop you making a request from a server you control to the server that does not implement CORS (the communication happening here is server to server, no browser is involved). Therefore, you can proxy a request through your own server to avoid CORS issues. Your application makes a request to your server, your server makes a request for the desired resource, and then your server returns that resource to your application.

Of course, you would need to make sure that your own server responds with the appropriate CORS header!

2. Proxy requests through native code

Similarly to the last solution, since CORS is implemented by browsers we can also avoid it by launching the request from native code on the device. You can do this using the native HTTP plugin in place of your normal HTTP requests.

This proxies the HTTP requests through native code, which completely circumvents CORS just like proxying the request through a server does. There isn’t really much difference to this approach and the previous one.

3. Downgrade to UIWebView (not recommended)

The reason a lot of people suddenly face CORS issues is that they upgrade from UIWebView to WKWebView (perhaps not knowingly). UIWebView is an old web view that is used to display your Ionic applications on iOS. WKWebView is a new web view that performs a lot better than its predecessor. However, UIWebView does not enforce CORS, whereas WKWebView does.

This means that you could downgrade to UIWebView to circumvent any CORS issues completely because UIWebView doesn’t care about CORS. However, this is not a good solution because you are sacrificing the overall performance of your application to fix an issue that can be solved in a better way.

Not a solution for CORS issues…

As well as all of the potential solutions for CORS issues that I have listed, I also wanted to specifically mention something that is not a solution.

I quite often see people confused who have installed some kind of CORS extension for the browser, or set some specific security flag to disable CORS. During development, this will circumvent CORS issues, but then when they move to production they start facing CORS issues.

These extensions or settings only modify your own browser to ignore CORS, so when other people start using the application, or you use it on a device, those CORS issues will still be present.

The only time using something like this is viable is if the CORS issues are only present for local development and you are trying to work around that. For example, maybe you are launching a PWA which works fine with CORS in production (since it is hosted on your own domain) but during development, you need to make requests from localhost.

Summary

CORS is a major source of frustration for many developers. Although the errors can be somewhat confusing, and the concept seems to be a little intimidating, once you understand the basics it is a reasonably simple concept with a fixed set of possible solutions.

What to watch next...