A Developer’s Tale: Conquering CORS in .NET

As developers, we often encounter hurdles that test our resilience and technical acumen. In this blog post,  I shall share my experience navigating through two prevalent challenges in modern web development: Cross-Origin Resource Sharing (CORS) issues in .NET and prop drilling in ReactJS. My journey through these obstacles not only honed my problem-solving skills but also equipped me with insights that I believe will be beneficial for fellow developers.

Tackling CORS in .NET Core

Cross-Origin Resource Sharing (CORS) is a security feature enforced by browsers to prevent malicious websites from accessing resources and data from another domain without permission. While developing a .NET backend for my project, I encountered CORS errors that prevented my ReactJS frontend from fetching data from the server. For instance, an error can show up like below –

Understanding the Root Cause

The CORS policy was blocking my requests because the origin (which is made up of a scheme, a hostname, and a port) of the request (my React app) did not match the domain of the server. This discrepancy triggers a security mechanism in browsers to protect against potential cross-site scripting attacks.

Broadly speaking, user agents add the Origin request header to:

  • cross origin requests
  • same-origin requests except for GET or HEAD requests (i.e. they are added to same-origin POST, OPTIONS, PUT, PATCH, and DELETE requests).

There are some exceptions to the above rules; for example, if a cross-origin GET or HEAD request is made in no-cors mode, the Origin header will not be added.

How Does CORS Work?

The OPTIONS request is a preflight request that is part of the CORS. The CORS mechanism that offers configuration access to shared resources. It remains applicable to a webpage that makes a request to another server apart from the origin server i.e., either the domain, protocol, or port differs. The browser then checks with the server if the request is permitted or not. If yes, the browser then performs the request. 

For instance, below the code showcases a PUT request to http://www.example.com/demo from foo.example.com for a preflight request to be performed –

OPTIONS /demo HTTP/1.1

Host: http://www.example.com

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)

  AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36

Accept: */*

Accept-language: nl-NL,nl;q=0.9,en-US;q=0.8,en;q=0.7

Connection: keep-alive

Origin: http://foo.example.com

Access-Control-Request-Method: PUT

However, in the absence of a preflight request, a server is still expected to allow a cross-origin request. For this, the browser requires an Access-Control-Allow-Origin header in the server’s response.

Implementing the Solution

To resolve this, I dived into the .NET Core middleware configuration. The approach involved enabling CORS in the Startup.cs file of my .NET project –

  • Defining a CORS Policy: First, I defined a CORS policy in the ConfigureServices method. This policy specifies the origins that can access the server resources.

services.AddCors(options =>

{

    options.AddPolicy(“AllowSpecificOrigin”,

        builder => builder.WithOrigins(“http://example.com”)

                          .AllowAnyMethod()

                          .AllowAnyHeader());

});

  • Applying the CORS Policy: Next, in the Configure method, the CORS policy was enabled for all incoming requests by adding app.UseCors(“AllowSpecificOrigin”); before app.UseAuthorization();.

This configuration allowed requests from the specified origin while keeping the application secure.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.