We need to configure CORS in .NET (or really in any other language) when an application’s front-end and back-end are being served from different domains, aka origins. And more than likely, during development, both the front-end and back-end will be running from different ports on localhost.
But what is CORS?
Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources.
From MDN
Basically, the server telling the browser “Hey, I only allow domains configured in my CORS policy, are you one of those?”
Enable CORS in .NET
CORS in .NET is enabled via middleware as follows
// Program.cs var builder = WebApplication.CreateBuilder(args); builder .services .AddCors(...); var app = builder.Build(); app.UseCors("PolicyName");
must be placed after UseCors
and before UseRouting
. This is to ensure that CORS headers are included in the response for both authorized and unauthorized calls. (From the official docs)UseAuthorization
Configure CORS in .NET
It is important to have the front-end origin as a configuration in appsettings.json so that when deploying to upper environments and production, a configuration transformation can happen.
{ "CorsSettings": { "FrontendOrigin": "http://localhost:3050" } }
Rather than having the configuration in Program.cs
, I like to create a static class and a static method returning an Action
.
// Program.cs var builder = WebApplication.CreateBuilder(args); builder .services .AddCors(Cors.Configure(builder.Configuration)); // Static method that takes in IConfiguration var app = builder.Build(); app.UseCors(Cors.FrontEndPolicyName); // Policy name as a static prop in Cors class
In my static Cors
class, I read the front-end origin setting to use in the configuration.
// Cors.cs public static class Cors { public const string FrontEndPolicyName = "AllowFrontEnd"; public static Action<CorsOptions> Configure(IConfiguration configuration) { var frontendOrigin = configuration .GetSection(nameof(CorsSettings)) .Get<CorsSettings>()? .FrontendOrigin; // Only in .NET 8. In .NET 7 use .ThrowIfNullOrEmpty ArgumentException.ThrowIfNullOrWhiteSpace(frontendOrigin, nameof(frontendOrigin)); return options => { options .AddPolicy(name: FrontEndPolicyName, policy => { policy .WithOrigins(frontendOrigin) .AllowAnyHeader() .AllowCredentials(); policy.WithMethods("POST","GET"); } ); }; } }
– Configure your front-end origin, or origins if more than oneWithOrigins
– As the name implies, allow all headers from the browser. UseAllowAnyHeader
if only allowing specific headersWithHeaders
– This is required if you have a login page. The front-end will send credentials to the server and the server will respond withAllowCredentials
. The server will block the request otherwise.Access-Control-Allow-Credentials: true
– Allow specific HTTP request methods. UseWithMethods
to allow all HTTP request methods.AllowAnyMethod
BONUS! Configure Fetch API on the Front-End
fetch(`URL`, { method: 'POST', mode: 'cors', credentials: 'include', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify('{}'), });
Mode
must be included as an option in the request. cors
must also be included.credentials
If credentials
are not included, the request will not include the authentication cookie, and authenticated routes will not be reached.