A Simple Configuration Based CORS Solution for ASP.NET Core

Advertisements

Skip the detail and show me the code.

Warning: some AWS services may have fees associated with them.

CORS, or Cross-Origin Resource Sharing — while simple in concept, seems to still mystify many developers. Simply put, CORS allows you to share resources from your “origin” with browser based consumers from a different origin.  In other words, if I have resources that exist on https://mydomain.xyz, JavaScript based consumers from http://yourdomain.xyz will not be able to access them. By enabling CORS we can share resources with other origins.  Get the full breakdown of CORS at Mozilla Developer Network web docs.

Unfortunately, all too often, developers enable CORS, but aren’t picky about what consumers they share with. Essentially, setting up CORS to share all resources, with all consumers.  In this tutorial we will show you how to set up a simple configuration based CORS solution for ASP.NET.

The Solution

1. Setup Configuration Constructs

Here we set up the configuration for this solution.  This json structure could be contained in the appsettings.json file or you could store it in a separate cors.json file, whatever suits you. You could even persist these structures to a store like Consul.

"cors": {
"enabled": true,
"allowAnyOrigin": false,
"origins": [
{ "uri": "http://yourdomain.xyz" },
{ "uri": "http://yourotherdomain.xyz" }
]
}
view raw appSettings.js hosted with ❤ by GitHub

The config structure is pretty straight forward.

  • We can enable CORS with the “enabled” value. 
  • If we want to share our resources with any consumer, we can set allowAnyOrigin to true. If you want to be picky about the consumers you share with, set allowAnyOrigin to false, and provide a list or origins.  In this example, origins is an array of objects, but you could just as easily use an array of strings. 

2. Create the C# class that Configures CORS and then enables it within Startup. For this example, we’ll call the class ConfigureCors.

3. The first method in the ConfigureCors class, ConfigureService, reads configuration and sets up the two policies.

public static void ConfigureService(IServiceCollection services, IConfiguration configuration)
{
services.AddCors(options =>
{
options.AddPolicy("AllowAnyOrigin",
builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
options.AddPolicy("AllowSpecificOrigins",
builder =>
{
List<CorsOrigin> origins = new List<CorsOrigin>();
configuration.GetSection("cors:origins").Bind(origins);
foreach (var o in origins)
{
builder.WithOrigins(o.Uri);
}
builder
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
}
view raw Startup.cs hosted with ❤ by GitHub

4. The other method in the ConfigureCors class, UseService, reads our configuration and decides which policy to use.

public static void UseService(IApplicationBuilder app, IConfiguration configuration)
{
bool enableCors = bool.Parse(configuration["cors:enabled"] ?? "false");
bool allowAnyOrigin = bool.Parse(configuration["cors:allowAnyOrigin"] ?? "false");
if (enableCors)
{
if (allowAnyOrigin)
{
app.UseCors("AllowAnyOrigin");
}
else
{
app.UseCors("AllowSpecificOrigins");
}
}
}
view raw Startup.cs hosted with ❤ by GitHub

5. Let’s pull it all together in Startup.cs. 

Within the ConfigureServices() method, we call ConfigureCors.ConfigureService(), passing in the collection of services and the configuration object.

public void ConfigureServices(IServiceCollection services)
{
ConfigureCors.ConfigureService(services, Configuration);
view raw Startup.cs hosted with ❤ by GitHub

In the Configure() method, we call ConfigureCors.UseService()  passing in the app and configuration objects.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
ConfigureCors.UseService(app, Configuration);
view raw Startup.cs hosted with ❤ by GitHub

Just The Code

1. Setup Config

"cors": {
"enabled": true,
"allowAnyOrigin": false,
"origins": [
{ "uri": "http://yourdomain.xyz&quot; },
{ "uri": "http://yourotherdomain.xyz&quot; }
]
}
view raw appSettings.js hosted with ❤ by GitHub

2. Create the method that creates the policies.

public static void ConfigureService(IServiceCollection services, IConfiguration configuration)
{
services.AddCors(options =>
{
options.AddPolicy("AllowAnyOrigin",
builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
options.AddPolicy("AllowSpecificOrigins",
builder =>
{
List<CorsOrigin> origins = new List<CorsOrigin>();
configuration.GetSection("cors:origins").Bind(origins);
foreach (var o in origins)
{
builder.WithOrigins(o.Uri);
}
builder
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
}
view raw Startup.cs hosted with ❤ by GitHub

3. Create the method that chooses the policy.

public static void UseService(IApplicationBuilder app, IConfiguration configuration)
{
bool enableCors = bool.Parse(configuration["cors:enabled"] ?? "false");
bool allowAnyOrigin = bool.Parse(configuration["cors:allowAnyOrigin"] ?? "false");
if (enableCors)
{
if (allowAnyOrigin)
{
app.UseCors("AllowAnyOrigin");
}
else
{
app.UseCors("AllowSpecificOrigins");
}
}
}
view raw Startup.cs hosted with ❤ by GitHub

4. Reference ConfigureCors.ConfigureService() in Startup.

public void ConfigureServices(IServiceCollection services)
{
ConfigureCors.ConfigureService(services, Configuration);
view raw Startup.cs hosted with ❤ by GitHub

5. Reference ConfigureCors.UseService() in Startup. 

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
ConfigureCors.UseService(app, Configuration);
view raw Startup.cs hosted with ❤ by GitHub

Advertisements
%d bloggers like this: