Understanding and Implementing CORS in .NET Core Web API
A practical guide to solving cross-origin issues and securing your web APIs for modern frontend frameworks.
Photo by Karen Chew on Unsplash
Introduction
If you have been working on different projects for a while now, you’ll know that front-end applications frequently interact with backend APIs. However, since backends are hosted on other domains or ports, this decoupled architecture is resilient but presents a challenge: CORS (Cross-Origin Resource Sharing).
In this post, we’ll explore what CORS is, why it matters, and how to implement it correctly in a .NET Core Web API project.
What is Same-Origin Policy?
It’s a good idea to discuss this first before we define CORS, so let’s get started.
Same-Origin Policy is a security mechanism imposed by modern web browsers to prevent web pages from requesting a different origin than the one that served the page.
Let’s review a bit what “origin” means:
- The protocol is either HTTP or HTTPS
- The domain, e.g., medium.com
- The port, e.g. 80,4200, 443
For these three parts to match, they must be considered to be of exact origin.
Let’s say a frontend application that runs at http://localhost:4200 wants to access a backend API that runs at https://localhost:5000.
Since these are not in the exact origin due to different ports, the browser blocks the frontend from accessing the backend by default.
What is CORS?
CORS (Cross-Origin Resource Sharing) is a browser security feature that restricts a web application from making HTTP requests to a different origin (domain, protocol, and port) than the one that served the web page.
The main goal of CORS is to:
- Protect users from cross-site attacks, such as CSRF or data leaks.
- Provide controlled access to resources on a different origin by specifying which origins are allowed to access the server.
This mechanism ensures that only trusted sources can communicate with your backend.
To recap, the Same-Origin Policy is enforced by the browser, which is the default behavior (checking if the request is going to the exact origin); if the request is to the same origin, it allows the request to proceed.
However, if not, it needs to check if CORS (on the target server) is configured, and the backend must respond with the correct CORS header; the browser will then allow the response.
Good Practices for Using CORS
First, avoid using “*” in production, as it can introduce numerous issues. Therefore, it is essential to permit only specific known domains. Hence, you need to allowlist trusted origins only.
Secondly, permit only the required methods, such as GET and POST, for your API, which means you need to restrict your HTTP methods.
Third, define the necessary request headers exclusively to minimize attack vectors and avoid using AllowCredentials() unless necessary.
Remember that this function allows cookies or HTTP authentication headers to be sent. Use it judiciously and never pair with “*” origin.
Implement CORS in .NET Core Web API
Let’s take a look at the code sample below.
using CORSPolicySample;
var builder = WebApplication.CreateBuilder(args);
var config = builder.Configuration;
// Add services to the container.
builder.Configuration.AddKeyVaultConfiguration();
builder.Services.AddControllers();
builder.Services.AddCors(options =>
{
var originValues = config.GetSection("AllowedOrigins").Value ?? "";
if (string.IsNullOrEmpty(originValues))
{
return;
}
var valuesInArray = originValues.Split(",");
options.AddPolicy("AllowedOrigins", builder =>
builder.WithOrigins(valuesInArray).AllowAnyHeader().AllowAnyMethod());
//Restrict HTTP Methods
options.AddPolicy("PublicApi", builder =>
builder.AllowAnyOrigin().WithMethods("Get").WithHeaders("Content-Type"));
});
var app = builder.Build();
app.UseCors("AllowedOrigins");
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
If you are interested in this line of builder.Configuration.AddKeyVaultConfiguration.
Here is the code sample below.
namespace CORSPolicySample;
public static class KeyVaultConfigLoader
{
public static void AddKeyVaultConfiguration(this ConfigurationManager config)
{
config.AddAzureKeyVault(
new Uri("https://azurekeyvaulttestjin02.vault.azure.net/"),
new DefaultAzureCredential());
}
}
I created a key vault to store the allowed hosts for my application.
So you’ll see that this is the value for the allowed hosts: “http://localhost:4200,http://localhost:3000,http://localhost:5173,http://localhost:8080”.
However, in case Azure Key Vault is not needed, we can always use the appsettings.json file.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
Conclusion
In this post, we have tackled and learned that CORS is a concept for building secure web APIs, which can be achieved by configuring CORS properly inside your .NET Core Web API.
This ensures a safe and controlled communication between your frontend and backend application without compromising the user’s security.

Top comments (0)