Cross-Origin Request Blocked

August 30, 2018 · 4 minute read · Tags: react

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?

Handy new tool alert: Check if you need CORs and generate the exact code to go in startup.cs

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.

But how do I allow my own front-end to bypass this policy?

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();
}

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.

Handy new tool alert: Check if you need CORs and generate the exact code to go in startup.cs

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"));

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/"));

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!

photo credit: mikecogh Stained Board in Brick Frame via photopin (license)

Join the Practical ASP.NET Newsletter

Ship better Blazor apps, faster. One practical tip every Tuesday.

I respect your email privacy. Unsubscribe with one click.

    Next up

    Edit and Replay your network requests, direct from the browser
    Half the battle with building a client-side web app (using Blazor, React etc) is figuring out what calls are being made to the network. Now you can see but also edit those requests and replay them…
    Quickly transform any mockup or design into a working Blazor prototype
    Even complicated applications can be broken down into small components, making them much less daunting to build.
    But, which flavor of ASP.NET?
    Blazor, Razor, MVC… what does it all mean?!