Cross-Origin Request Blocked?

jonhilt

Jon Hilton

Posted on September 13, 2018

Cross-Origin Request Blocked?

You've built a shiny new API using ASP.NET Core.

You can call it via a web browser (or one of my favourite tools, Insomnia) and everything works perfectly.

Then you try to call it from your front-end (React, Angular or whatever) and boom.

You get a cryptic error about a Cross-Origin Request being blocked, because the Same Origin Policy disallows reading the remote resource at somewhere or other...

So what is this?

All modern browsers enforce something called a "Same origin policy".

This is designed to prevent some random web site on the Internet from being able to make requests to your API.

Why does the Same Origin Policy exist?

Take this example.

I stand up an API at https://jonhilton.io/api and a front-end at the same domain (using something like React, Angular).

So far so good, I launch the site, everyone starts using https://jonhilton.io, which interacts with my API and everything is well in the world.

But then, disaster. One of my users is tricked into going to a spoof site, which looks like mine but is actually hosted over at https://dodgygeezer.com.

The page at https://dodgygeezer.com includes javascript to make calls to my api.

Without the same origin policy, there would be nothing to stop https://dodgygeezer.com from making these requests.

Same Origin Policy to the rescue

The same origin policy (implemented in the browser) does a number of things to try and protect your site from malicious use.

The main aspect we're interested in when talking about AJAX requests is its ability to prevent code which is executed in the browser (e.g. your's or someone else's javascript) from making certain AJAX calls to a site at a different origin.

Origin refers to the domain of the page which serves the javascript.

For this example, the origin for legitimate requests from my site would be https://jonhilton.io

The origin for the dodgy imposter site would be https://dodgygeezer.com

The same origin policy attempts to limit what a client can do if it makes requests from an origin which the server does not trust.

By default, your ASP.NET Core Web API will allow any requests made from a site at the same origin. So any javascript served for https://jonhilton.io will be fine.

So why the problem when I'm calling my own API?

This is all well and good, but why are you seeing this error when your own front-end app tries to communicate with your api?

Well, if they're both served from the same domain you'll be fine.

Front-end: https://jonhilton.io
Back-end: https://jonhilton.io/api

Both are served from https://jonhilton.io and therefore have the same origin.

Front-end: https://jonhilton.io
Back-end: https://api.jonhilton.io

Now we have the problem. The sub-domain here means that these are considered to be different origins.

If you're running your api and front-end site locally you'll have the same problem due to different ports being used.

Front-end: https://localhost:3000
Back-end: https://localhost:5000

The different port here means these are considered different origins.

Alright then, how do I allow my own front-end to bypass this policy?

Quick and easy

If you want to generate the CORS code for your own applications (and get a handy explanation of the generated code) check out CorsDot.net.

It's a little site I created to take the headache out of configuring CORs. Check it out and let me know how you get on :-)

An example of CORs configuration

Let's take this example.

Front-end: https://jonhilton.io
Back-end: https://api.jonhilton.io

If we want https://jonhilton.io to be able to make requests to https://api.jonhilton.io we need to configure our API to allow those requests by implementing a CORS policy for the API.

CORS = Cross Origin Resource Sharing

CORS lets you control which resources running in the browser (front-end applications) are expected to call your API.

In ASP.NET Core 2.x this is simply a matter of configuration.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // ...

    app.UseCors(builder =>
        builder.WithOrigins("https://jonhilton.io"));

    app.UseHttpsRedirection();
    app.UseMvc();
}
Enter fullscreen mode Exit fullscreen mode

Make sure the app.UseCors call is before app.UseMVC otherwise it will have no effect on requests to your app which trigger the MVC pipeline (which is all MVC and API requests!).

And that's it. If you examine any responses from your API now you'll notice they include this response header.

This "Access-Control-Allow-Origin" header is the magic that ensures you won't see the dreaded CORS error anymore.

If you want more than one url to be permitted, you can simple add more to the list.

app.UseCors(builder =>
    builder.WithOrigins(
        "https://jonhilton.io", 
        "https://localhost:3000"));
Enter fullscreen mode Exit fullscreen mode

GOTCHA: Omit the trailing slash!

Watch out for one thing. It's very easy to accidentally include a trailing slash when adding an origin to the permitted origins list.

app.UseCors(builder =>
    builder.WithOrigins(
        "https://jonhilton.io/", 
        "https://localhost:3000/"));
Enter fullscreen mode Exit fullscreen mode

But if you do, you'll find you start seeing the "same origin policy" error again. This is one of those problems which can have you tearing your hair out because it "looks right" but the trailing slash will break your CORS!

💖 💪 🙅 🚩
jonhilt
Jon Hilton

Posted on September 13, 2018

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related