CORS Configuration with Umbraco 13 and .NET Core
A quick step through on setting up custom CORS (Cross-Origin Resource Sharing) configuration with multiple CORS policies within a .NET Core Umbraco CMS project.
This is something that I wanted to note down and share as I couldn’t find alot of details on how to properly configure this on a solution that I’ve been working on. I happened to find the answer in a small comment on the Umbraco Community Forum that was a “try this out, it might work?” type of comment and not a full correctly highlighted response (it can be found here: https://our.umbraco.com/forum/using-umbraco-and-getting-started/110188-cors-in-umbraco-10-how-to#comment-348666, Thanks for your answer!)
I was wracking my brain to try and use all the answers out there and this was the one that solved my issue in the end, so I thought I’d share it for anyone else out there.
*NOTE: If you just want to skip to the solution and get past all the explanation, issues and some of my ramblings…. then click here to go to the solution.
What is CORS (Cross-Origin Resource Sharing)?
For a full explanation of CORS, you can have a read on the MDN Web Docs Here, in short, CORS is used to secure resources for a website so it should only allow browsers that are on a URL to access resources on the same domain.
This is a process in place to prevent cross-site request forgery(CSRF) where they can send fake requests from someones browser to another application. So it’s a good security measure to have in place on your site.
Why Have Multiple CORS Policies on a Site?
Some projects are fine to have everything accessible to any application, such as API Gateways, or a site that is setup to share it’s resources to anyone.
Some sites have everything locked down so they have a strict CORS policy that only allows their resources to be access by browsers that are accessing it through the same URL or domain.
However, in some situations you may want some resources to be restricted to the same site policy, but you also want some others to be accessible to any resource.
In my situation this is one of the sites I’m working on has a frontend and also an API gateway, most API’s are fine to be only accessible to the site that is running it, however there were 1 or 2 that needed to be accessible via other external applications.
In this case, I need to have 1 general CORS policy for most of the project and another one for those specific endpoints.
The Issue with Multiple CORS Policies and Umbraco 13 with .NET Core
This is all well and good, and there are many resources online that show how to have multiple active policies for CORS in .NET Core and exactly where to put the code for it.
However, whenever I tried to use nearly all the solutions, I kept either getting errors saying that “CORS is not configured correctly”, it was applying the CORS policy to everything, or it was not applying the CORS policy to anything.
I was wracking my brain and searching all over to find the solution, and then I found it!
All the documents say it’s important to position the UseCors() code in the Program.cs (yes, we’re using .NET 8, so no Startup.cs) between specific calls such as UseRouting() and UseEndpoints(), however, these are not present in an Umbraco project.
Even Github Copilot and ChatGPT were saying the same as all the other examples on where to put it and could not offer a suggestion that worked!
But, what I found to work is here…
Multiple CORS Policy Solution in Umbraco 13
Ok, so in the Program.cs file I have setup a few custom CORS policies to be used within the project:
# region CORS policy allowed origins
var origins = configuration.GetSection("CorsAccessPolicyDomains").Get<string[]>();
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyCorsPolicy",
builder =>
{
builder.WithOrigins(origins)
.AllowAnyHeader()
.AllowAnyMethod();
});
options.AddPolicy(name: "AllowAllOrigins",
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
# endregion
So here I have the example of getting the CORS domains that are permitted in the CORS policy from the applicationSettings.json and then I’m using them for my MyCorsPolicy rule. This is the one that is restricting access to ONLY the domains that are in this list.
Then I have another rule, AllowAllOrigins, which like the name suggests, allows any application access.
This just adds the rules to the project, but doesn’t apply them.
We need to now activate the CORS Middleware so the policy functions and…
It’s important where you place the next rule or it will not work!
This is where I had all the issues, all the documents and resources (even the clever Copilot and ChatGPT couldn’t help.
Add the app.UseCors() within the UseUmbraco → WithMiddleware section
app.UseUmbraco()
.WithMiddleware(u =>
{
// NOTE: Enable CORS needs to be before UseBackOffice within the middleware to function
app.UseCors(); // Use the CORS policy
u.UseBackOffice();
u.UseWebsite();
})
.WithEndpoints(u =>
{
u.UseInstallerEndpoints();
u.UseBackOfficeEndpoints();
u.UseWebsiteEndpoints();
});
Everything I could find was saying to add it before the UseUmbraco call, but that Umbraco Community post was all I needed to fix this and have CORS with multiple rules working.
But, you do need to add [EnableCors] attributes to your resources for the rules to apply.
Adding CORS Rules to Resources
Now that the CORS policies have been added to the project and CORS Middleware is running within Umbraco, you need to add the attributes to your resources/controllers.
You can do it at the top level of your controllers:
[EnableCors("MyCorsPolicy")]
[Route("[controller]")]
public class MyController : UmbracoApiControllerBase
And this will apply the policy to all the endpoints within the controller.
Now, if you wanted to change the policy for a specific endpoint within the controller, you can simply add the other CORS policy to that method and it will use the new policy instead of the class applied policy:
[EnableCors("MyCorsPolicy")]
[Route("[controller]")]
public class MyController : UmbracoApiControllerBase
{
...
[EnableCors("AllowAllOrigins")]
[HttpGet()]
public async Task<IActionResult> GetAsync()
{
...
}
...
}
This will now allow you to have multiple CORS policies within your Umbraco Controllers to have more control over your access to your endpoints.
Summary
CORS is an important security feature that should be used with your online projects to manage access and secure your resources from unwanted access.
Settings up and configuring the resources can be slightly different between different projects, but it’s important to make sure it’s still applied where required.
I hope this helps anyone that gets stuck in the same boat as I was and speeds up your troubleshooting.
Anyway, until next time, happy Dev-ing!
There is also the possibility to add post pipelines to Umbraco. That would also make your cors policy work:
services.Configure<UmbracoPipelineOptions>(options =>
{
options.AddFilter(
new UmbracoPipelineFilter("CorsPolicy",
postPipeline: applicationBuilder =>
{
applicationBuilder.UseCors();
}
));
});