ASP.NET Core  

How to Fix CORS Error in ASP.NET Core?

CORS (Cross-Origin Resource Sharing) errors are one of the most common issues developers face when building ASP.NET Core Web APIs that are consumed by frontend applications such as Angular, React, Vue, or mobile clients. In production environments, improper CORS configuration can block legitimate requests, expose security vulnerabilities, or break integration between microservices. This guide explains what CORS is, why CORS errors occur, how the browser enforces it, and how to fix CORS issues in ASP.NET Core using secure and production-ready configurations.

What is CORS?

CORS (Cross-Origin Resource Sharing) is a browser security mechanism that restricts web pages from making requests to a different domain, protocol, or port than the one from which the page was served.

Origin consists of three components:

  • Protocol (http or https)

  • Domain (example.com)

  • Port (80, 443, 5001, etc.)

If any of these differ, the request is considered cross-origin.

Real-world analogy:

Think of CORS as a security guard at an office building. Even if someone has valid documents (HTTP request), the guard checks whether they are allowed to enter from another company (different origin). If not approved, access is denied.

Since the domains differ, the browser blocks the request unless the API explicitly allows it.

Why Does CORS Error Occur?

CORS errors occur because:

  • The server does not send the Access-Control-Allow-Origin header

  • The origin is not allowed in CORS policy

  • Credentials are sent but not allowed

  • Preflight OPTIONS request fails

  • HTTP and HTTPS mismatch

Important:

CORS is enforced by the browser, not by ASP.NET Core. Tools like Postman do not show CORS errors because they do not enforce browser security rules.

How CORS Works Internally

When a browser makes a cross-origin request:

  1. Browser checks if request is simple or complex.

  2. For complex requests (PUT, DELETE, custom headers), browser sends a preflight OPTIONS request.

  3. Server must respond with proper CORS headers.

  4. If headers allow the origin, browser sends actual request.

  5. If headers are missing or invalid, browser blocks it.

Example of required response headers:

  • Access-Control-Allow-Origin

  • Access-Control-Allow-Methods

  • Access-Control-Allow-Headers

If these are missing, you will see errors like:

"Access to fetch at 'API_URL' from origin 'FRONTEND_URL' has been blocked by CORS policy."

Step-by-Step: Fix CORS Error in ASP.NET Core

Step 1: Configure CORS in Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowFrontend",
        policy =>
        {
            policy.WithOrigins("https://myfrontend.com")
                  .AllowAnyHeader()
                  .AllowAnyMethod();
        });
});

builder.Services.AddControllers();

var app = builder.Build();

app.UseCors("AllowFrontend");

app.MapControllers();

app.Run();

Explanation:

  • AddCors registers CORS services.

  • AddPolicy defines allowed origins.

  • UseCors enables middleware.

  • WithOrigins restricts access to specific domain.

Step 2: Allow Multiple Origins (If Required)

policy.WithOrigins(
    "https://myfrontend.com",
    "https://admin.myfrontend.com");

Step 3: Allow Credentials (If Using Authentication)

If your API uses cookies or authentication tokens:

policy.WithOrigins("https://myfrontend.com")
      .AllowAnyHeader()
      .AllowAnyMethod()
      .AllowCredentials();

Important:

When AllowCredentials() is used, you cannot use AllowAnyOrigin().

Difference Between AllowAnyOrigin and WithOrigins

FeatureAllowAnyOriginWithOrigins
Security LevelLowHigh
Suitable for ProductionNoYes
Allows Specific DomainNoYes
Supports CredentialsNoYes
Recommended UsageDevelopment onlyProduction environments

In production systems, always prefer WithOrigins for security.

Handling Preflight OPTIONS Request

Complex requests (PUT, DELETE, Authorization headers) trigger preflight.

Ensure:

  • UseCors is placed before MapControllers

  • OPTIONS method is not blocked by middleware

  • Firewall or reverse proxy is not blocking OPTIONS

If using IIS or Nginx, verify configuration allows OPTIONS requests.

Real Production Scenario

Imagine an ASP.NET Core API deployed on Azure App Service and a React frontend hosted on Azure Static Web Apps. Everything works locally, but after deployment, login fails.

Reason:
The backend did not allow the frontend production URL in CORS policy.

Fix:

Add production domain to WithOrigins() and redeploy.

Result:

Authentication works correctly and browser stops blocking requests.

Common Mistakes Developers Make

  • Using AllowAnyOrigin in production

  • Forgetting to enable UseCors middleware

  • Placing UseCors after MapControllers

  • Not handling HTTPS mismatch

  • Forgetting to allow credentials

  • Ignoring preflight request failures

When NOT to Use Open CORS Policy

Avoid open CORS policies when:

  • API handles sensitive data

  • Authentication is involved

  • Application is public-facing

Open CORS can expose your API to abuse and cross-site attacks.

Advanced Scenario: Dynamic CORS Policy

If your application supports multi-tenant domains, you can dynamically validate origins:

policy.SetIsOriginAllowed(origin =>
{
    return origin.EndsWith(".mydomain.com");
});

This allows subdomains while maintaining security control.

Best Practices for CORS in ASP.NET Core

  • Restrict origins in production

  • Use HTTPS everywhere

  • Monitor preflight failures

  • Avoid wildcard origins

  • Test CORS after deployment

  • Combine with proper authentication and authorization

Summary

Fixing CORS errors in ASP.NET Core requires understanding that CORS is a browser-enforced security mechanism that blocks cross-origin requests unless explicitly allowed by the server. By properly configuring CORS policies using AddCors, restricting allowed origins with WithOrigins, enabling credentials securely, and ensuring middleware order is correct, developers can resolve cross-origin issues without compromising security. Instead of using open policies like AllowAnyOrigin in production, it is essential to implement restricted and well-defined CORS configurations that protect APIs while enabling seamless communication between frontend and backend applications.