Due to the same-origin policy, most browsers restrict making requests to different domains than the originally served the website. This is a security feature that prevents a harmful site from accessing sensitive data on other sites. If you are developing an API though, cross-origin requests (CORS) are something you want to allow to make sure client applications can use the API.

Using a named CORS policy has been my preferred approach to enable CORS in .NET Core. This is simply because it applies the CORS policy to all endpoints in the API.

Code snippet below shows that I am opening up the API to the whole world:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
    {
        builder.AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader()
            .AllowCredentials();
    }));
    ...
}
public void Configure(IApplicationBuilder app,IHostingEnvironment env)
{
    ...
    app.UseCors("CorsPolicy");
    ...
}Code language: C# (cs)

Unfortunately, this does not appear to work and I get the following error when an AJAX request is issued in Chrome:

[Error] Access to XMLHttpRequest at ‘https://api.com/end-point’ from origin ‘https://mywebsite.com’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

Safari on Mac OS logs the following errors:

[Error] XMLHttpRequest cannot load https://staging.xyz.com/api/orders due to access control checks.

[Error] Failed to load resource: Preflight response is not successful

AllowAnyOrigin affects preflight requests and the Access-Control-Allow-Origin header. It sets the header to be a wildcard '*', which is ignored by browser as it is considered insecure.

Solution

The solution is to avoid using AllowAnyOrigin when defining the CORS policy and specify the origins that will consume your API.

services.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
{
    builder.WithOrigins("https://mywebsite.com")
        .AllowAnyMethod()
        .AllowAnyHeader()
        .AllowCredentials();
}));Code language: C# (cs)

The origin can be a full domain such as above or a sub domain. It is also possible to use wildcard subdomains:

services.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
{
    builder.WithOrigins("https://*.mywebsite.com")
        .SetIsOriginAllowedToAllowWildcardSubdomains();
}));Code language: C# (cs)

Umut Esen

Software Engineer specialising in full-stack web application development.

Leave a Reply