In this post, we are going to talk about enabling CORS in ASP.NET Core Web Applications.

You can find the source code for this blog post on GitHub.

This post is divided into the following sections:

Before we understand how to enable CORS in ASP.NET Core applications, we need to understand an important concept in the web application security model called the Same-Origin policy.

About Same-Origin and What it Means

Two URLs are considered to have the same origin if they have the same URL scheme (HTTP or HTTPS), same hostname (domain name) and same port number (the endpoint at which applications talk to each other).

What Is the Same-Origin policy?

The Same-origin policy states that a Web browser will only allow communication between two URLs if they belong to the same origin. That is, the client app (https://example.com) cannot communicate with the server app (https://example.net) as they belong to a different origin. This policy exists to isolate potentially malicious scripts from harming other documents on the web.

Let’s come to the core of the article.

What Is CORS?

But there are some cases where Cross-Domain scripting is desired and the idea of the open web makes it compelling.

Cross-Origin Resource Sharing is a mechanism to bypass the Same-Origin policy of a Web browser. Specifically, a server app uses additional HTTP headers to tell a browser that it is fine to load documents (from its origin) in a few selected client apps (of different origin).

Let’s go deep.

How Does CORS Work?

In this section, let’s learn how CORS works at the level of HTTP messages.

Inner Workings

Let’s have a look at the picture below. There is a client app (https://example.com) sending a GET request to a server app (https://example.net) for some resource:

Enabling CORS in ASP.NET Core

All modern browsers set the Origin header automatically, which indicates the domain of the site is making the request.

If the server allows Cross-origin requests from the Origin (https://example.com), it sets the Access-Control-Allow-Origin header with its value matching the origin header’s value from the request.

In other way, if the server doesn’t include this header, the request fails. The browser shall receive the response data, but this data shall not be accessible to the client.

That’s how a simple CORS request works.

Preflight Requests

Sometimes, instead of a simple GET request, a client may need to send requests like PUT, DELETE etc. For such requests, the browser sends an additional request (an OPTIONS request) called a Preflight request. This is done just before the actual request to make sure that the original request succeeds. If it does, the browser sends the actual request.

This diagram illustrates such a scenario:

Preflight RequestA preflight request

Actual RequestActual request

Demo

Enough of the theory. Let’s get to the action.

Same-Origin Policy in Action

In the demo, let’s create two projects. One is a server app which we are going to deploy to Azure. And the other the client app, which we are going to run locally.

In Visual Studio, let’s create an MVC project. This will be our server app:

New MVC Project

If you are new to Azure deployment, then check out this article. You can also get a free Azure account here.

Once the project is created, let’s deploy it to Azure Web App:

Azure web app deploy

After deployment, the server app is hosted at testapp1158.azurewebsites.net:

Live page

Next, let’s create a Client app. Again, we are going to create another ASP.NET Core MVC project, which runs locally. We have both client and the server app running and they belong to different origins.

To make cross-origin requests, let’s go to Solution Explorer, navigate to Views -> Home -> Index.html. Let’s go to the bottom of the document and add the following piece of code:

This markup creates a button and, when the user clicks the button, it calls a function.

Just below the markup, let’s create a script tag with the code that makes an ajax request to the server app when the user clicks the button:

Since we haven’t enabled CORS on the server app, the server app doesn’t set any headers and the browser rejects the response.

So, if we navigate to the client app running locally and click the Try button, we should see an error:

error

Okay! Let’s get to the best part.

Enabling CORS

Now that we have seen the Same-Origin policy in action, let’s enable CORS.

There are 3 steps to enable CORS in a server app:

  • First of all, we need the Microsoft.AspNetCore.Corspackage in our project. It should be already installed in our project via the Microsoft.AspNetCore.App package, which is created as soon as our project was created. But if for some reason, you can’t see that package in the Solution Explorer, go to Tools -> NuGet Package Manager -> Manage NuGet Packages for Solution. Search for Microsoft.AspNetCore.Cors and install the package
  • Next, we need to inject CORS into the container so that it can be used by the application. In Startup.cs class, let’s go to the ConfigureServices method and register CORS:

  • To enable CORS for our application, let’s add the CORS middleware to the HTTP request pipeline in the Configure method, just below the if-else statement. Let’s specify an URL from where the CORS requests are allowed when building the CORS policy. Here, we have given the Client URL:

Let’s save our Server app and re-publish it to the App Service. Now let’s open the client app and click the Try button. We should see an HTML document retrieved from the server app:

data from server app

Congratulations! We have successfully enabled CORS.

Okay, but that’s not all. Let us show you a few more tricks.

Configuring CORS Requests

If we only want to allow CORS requests to a selected few methods, instead of enabling CORS at the entire application level, we can also enable CORS at the controller level or at the action level.

So to enable CORS at the Action level, let’s replace the code we added previously in the ConfigureServices method with:

This method defines a named CORS policy called,AllowOrigin that allows cross-origin requests from our client app. And now, instead of specifying CORS middleware in the HTTP request pipeline in theConfiguremethod , we are going to select this policy at runtime at the Action level.

So, in our server app, let’s go to Controllers -> HomeController.cs and add the EnableCors decorator to the Index method:

Let’s save the project and deploy the server app to Azure again.

In the client app, in the Index.cshtml file, let’s update the serviceURL in the script section:

Now, if we run the project without debugging, we should still see the output:

data from server app

But, if we update the serviceUrl in client app to access any other method in Home Controller in the server app, we should see an error output. The updated serviceURL:

shall give the expected output as:

error

Similarly, we can do this per controller as well.

It’s not over. More power to you.

Configure CORS Policy Options

In ASP.NET Core, we can use various options to customize our CORS policy.

For example, to only allow GET methods on our resource, let’s use the WithMethods method when we define the CORS policy:

If we need to allow any origin to access the resource, let’s use AllowAnyOrigin instead of WithOrigins:

And ASP.NET Core provides several tools to customize what kind of requests we would like to allow.

Conclusion

In conclusion, think of CORS as a relaxation attempt to the more restrictive Same-Origin policy. On the one side, there is a growing need for security on the web. And on the other, there is the need to integrate web services. CORS provides rich tools for our need for an open and secure web and ASP.NET Core allows us to take advantage of CORS in our cross-platform web applications.

If you have enjoyed reading this article and if you would like to receive the notifications about the freshly published Web Development content we encourage you to subscribe to our blog.