Missing 'Access-Control-Allow-Origin' Header on Preflight Request

By FoxLearn 1/10/2025 4:32:49 AM   71
If you're encountering the following error when trying to call a CORS-protected .NET Core API endpoint from a browser:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:5100' is therefore not allowed access. The response had HTTP status code 405.

What Is a Preflight Request?

A preflight request is made by the browser to check if the server supports CORS (Cross-Origin Resource Sharing) for the specific resource. When making a request (like POST, PUT, or DELETE) with custom headers (such as application/json), the browser sends a preflight OPTIONS request first. If the server responds with appropriate CORS headers, the browser proceeds with the actual request.

If the preflight request fails due to missing or incorrect CORS configuration, you will encounter errors like the one above.

Fixing CORS Issues in .NET API: Resolving 'No Access-Control-Allow-Origin' Error

Here's how to resolve the 'No Access-Control-Allow-Origin' error.

Ensure 'OPTIONS' Method Is Allowed

The error could be due to the fact that the OPTIONS method isn't allowed in your CORS configuration. The OPTIONS request is essential for the browser to verify CORS permissions before proceeding with the main request.

app.UseCors(builder =>
{
    builder
        .WithOrigins("http://localhost:5100", "https://localhost:5100") // Specify allowed origins
        .SetIsOriginAllowedToAllowWildcardSubdomains() // Allow subdomains if necessary
        .AllowAnyHeader() // Allow any header
        .AllowCredentials() // Allow credentials (cookies, headers, etc.)
        .WithMethods("GET", "PUT", "POST", "DELETE", "OPTIONS") // Allow relevant HTTP methods
        .SetPreflightMaxAge(TimeSpan.FromSeconds(3600)); // Cache the preflight response for 1 hour
});

Check for Duplicate CORS Configuration

Ensure that CORS is only configured once in your application. You should add it both in the builder.Services and app.UseCors() method. If you've added it in both places, make sure it’s not duplicated.

First, add CORS to the service collection:

var builder = WebApplication.CreateBuilder();
builder.Services.AddCors();

Then, configure CORS middleware in the application:

var app = builder.Build();
app.UseCors(builder =>
{
    builder
        .WithOrigins("http://localhost:5100", "https://localhost:5100")
        .AllowAnyHeader()
        .AllowCredentials()
        .WithMethods("GET", "PUT", "POST", "DELETE", "OPTIONS")
        .SetPreflightMaxAge(TimeSpan.FromSeconds(3600));
});

Verify the Sequence of Middleware Calls

CORS must be configured early in the middleware pipeline before routing and controller mapping. It should be placed before any middleware that handles requests.

var app = builder.Build();

// Ensure CORS is defined first in the middleware pipeline
app.UseCors(builder =>
{
    builder
        .WithOrigins("http://localhost:5100", "https://localhost:5100")
        .AllowAnyHeader()
        .AllowCredentials()
        .WithMethods("GET", "PUT", "POST", "DELETE", "OPTIONS")
        .SetPreflightMaxAge(TimeSpan.FromSeconds(3600));
});

// Now define other middlewares and routes
app.MapControllers();
app.UseRouting();
app.UseHttpsRedirection();

if (app.Environment.IsProduction())
{
    app.UseTokenAuthentication();
}

app.Run();

Allow ‘OPTIONS’ Requests in Load Balancer

If your API is behind a load balancer, make sure the load balancer is configured to allow OPTIONS requests. Sometimes, load balancers can block OPTIONS requests, which will prevent preflight checks from succeeding.

Check the load balancer’s configuration and ensure it does not restrict the OPTIONS HTTP method.

By ensuring the proper CORS configuration, allowing the OPTIONS method, defining CORS in the correct order, and verifying load balancer settings, you can resolve the issue of the missing Access-Control-Allow-Origin header.