# Implement CORS in .NET Core the Production-Way

URL: https://answers.mindstick.com/blog/321/implement-cors-in-dot-net-core-the-production-way

Cross-Origin 
Resource 
Sharing (CORS) is one of the most commonly misconfigured 
features in 
modern 
APIs. Many 
developers 
enable AllowAnyOrigin() during 
development and accidentally ship it to 
production — 
creating unnecessary security risks.
In this article, you'll 
learn how to 
implement CORS properly in ASP.NET Core for real-world production environments.
We’ll cover:
What CORS actually isWhy 
browsers 
block requestsSecure production configurationEnvironment-based policiesHandling credentials correctlyCommon mistakesBest 
practices for 
enterprise APIs
Official documentation:
ASP.NET Core CORS Documentation
What is CORS?
CORS (Cross-Origin Resource Sharing) is a 
browser security 
mechanism that 
controls how 
resources are requested from 
different domains.
Example:
Frontend:
https://app.example.com
Backend 
API:
https://api.example.com
Since the 
origins are different, the browser enforces CORS 
rules.
Without proper configuration, requests 
fail with errors like:
Access to fetch at 'https://api.example.com'
from origin 'https://app.example.com'
has been blocked by CORS policy
Understanding Origin
An origin consists of:
Scheme + Host + Port
Examples:
URL
Origin
https://example.com
Different
http://example.com
Different
https://api.example.com
Different
https://example.com:5001
Different
Even a 
port 
change creates a different origin.
Why CORS Exists
CORS protects 
users from 
malicious 
websites making unauthorized requests 
using browser credentials.
Without CORS, a malicious 
site could:
Read sensitive API responsesSteal authenticated dataAbuse user sessions
CORS is enforced by browsers, not by servers.
The Biggest Production Mistake
Many 
tutorials show this:
builder.Services.AddCors(options =andgt;
{
    options.AddPolicy("OpenPolicy", policy =andgt;
    {
        policy
            .AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader();
    });
});
This is acceptable only for local development.Never use unrestricted CORS in production for authenticated APIs.
Production-Ready CORS Configuration
The correct 
approach is:
Explicitly allow 
trusted originsRestrict methodsRestrict headersHandle credentials securelySeparate environments
Step 1 — Configure Allowed Origins
appsettings.json
{
  "Cors": {
    "AllowedOrigins": [
      "https://app.example.com",
      "https://admin.example.com"
    ]
  }
}
This keeps configuration centralized and environment-friendly.
Step 2 — Register CORS Policy
Program.cs (.NET 6+)
// Create builder
var builder = WebApplication.CreateBuilder(args);
// Read allowed origins from configuration
var allowedOrigins = builder.Configuration
    .GetSection("Cors:AllowedOrigins")
    .Getandlt;string[]andgt;();
// Register CORS
builder.Services.AddCors(options =andgt;
{
    options.AddPolicy("ProductionCorsPolicy", policy =andgt;
    {
        policy
            // Allow only trusted domains
            .WithOrigins(allowedOrigins)
            // Restrict HTTP methods
            .WithMethods("GET", "POST", "PUT", "DELETE")
            // Restrict headers
            .WithHeaders("Content-Type", "Authorization")
            // Allow cookies/auth tokens if needed
            .AllowCredentials();
    });
});
// Add controllers
builder.Services.AddControllers();
var app = builder.Build();
// Use CORS before authentication/authorization
app.UseCors("ProductionCorsPolicy");
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Why AllowCredentials() Matters
If your frontend sends:
CookiesJWT bearer 
tokensSession authenticationThen credentials handling becomes important.
Example frontend 
request:
fetch("https://api.example.com/data", {
    credentials: "include"
});
When credentials are enabled:
AllowAnyOrigin() is forbiddenOrigins must be 
explicitThis is intentional for security reasons.
Correct Middleware Order
Middleware 
order matters in ASP.NET Core.
Correct:
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
Incorrect ordering can cause:
Failed preflight requestsMissing headersAuthentication issues
Environment-Based CORS
Production and development usually 
require different rules.
appsettings.Development.json
{
  "Cors": {
    "AllowedOrigins": [
      "http://localhost:3000",
      "https://localhost:5173"
    ]
  }
}
appsettings.Production.json
{
  "Cors": {
    "AllowedOrigins": [
      "https://app.example.com"
    ]
  }
}
This prevents accidentally exposing development origins in production.
Supporting Multiple Frontends
Production APIs often support:
Web 
applicationsAdmin dashboardsMobile gatewaysPartner portals
Use explicit origin lists:
policy.WithOrigins(
    "https://app.example.com",
    "https://admin.example.com",
    "https://partner.example.com"
);
Restrict Headers Properly
Avoid:
.AllowAnyHeader()
Prefer:
.WithHeaders(
    "Content-Type",
    "Authorization",
    "X-Requested-With"
)
This reduces 
attack 
surface and keeps policies predictable.
Restrict Methods Properly
Avoid:
.AllowAnyMethod()
Prefer:
.WithMethods("GET", "POST")
Only expose what your API truly supports.
Handling Preflight Requests
Browsers 
send an OPTIONS request before certain cross-origin calls.
This is called a preflight request.
Example:
OPTIONS /api/users HTTP/1.1
Origin: https://app.example.com
Access-Control-Request-Method: POST
ASP.NET Core handles this 
automatically when CORS is configured correctly.
Common Production Mistakes
1. Using AllowAnyOrigin()
Unsafe for authenticated APIs.
2. Mixing Credentials with Wildcards
Invalid:
.AllowAnyOrigin()
.AllowCredentials()
ASP.NET Core will reject this configuration.
3. Applying CORS Too Late
Wrong middleware order 
causes failures.
4. Forgetting Reverse Proxy Headers
When using:
NginxIISAzure 
App GatewayCloudflare
Ensure 
proxy configuration does not strip CORS headers.
Applying CORS to Specific Controllers
Instead of globally enabling CORS:
[EnableCors("ProductionCorsPolicy")]
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
}
Namespace required:
using Microsoft.AspNetCore.Cors;
This is useful for:
Public APIsMulti-tenant systemsAdmin-only endpoints
Dynamic CORS for Multi-Tenant SaaS
Some 
SaaS applications need 
dynamic origins.
Example:
policy.SetIsOriginAllowed(origin =andgt;
{
    return origin.EndsWith(".example.com");
});
Use carefully.
Validate origins properly to avoid 
subdomain abuse.
Production Security Recommendations
Use HTTPS Only
Always allow secure origins:
https://app.example.com
Never allow plain HTTP in production.
Log Rejected Origins
Track 
suspicious cross-origin attempts.
Example use cases:
Threat monitoringMisconfigured clientsAbuse detection
Keep Origins Configurable
Avoid hardcoding origins directly into 
source code.
Use:
Configuration filesEnvironment variablesSecret managers
Separate Public and Internal APIs
Internal admin APIs should not share permissive CORS rules with public APIs.
Example Enterprise Setup
builder.Services.AddCors(options =andgt;
{
    options.AddPolicy("EnterprisePolicy", policy =andgt;
    {
        policy
            .WithOrigins(
                "https://app.example.com",
                "https://admin.example.com"
            )
            .WithMethods("GET", "POST", "PUT")
            .WithHeaders(
                "Authorization",
                "Content-Type"
            )
            .AllowCredentials();
    });
});
This configuration is:
ExplicitSecureMaintainableProduction-friendly
Testing CORS
Useful tools:
Browser DevToolsPostmancurlNetwork 
tab inspection
Example curl request:
curl -H "Origin: https://app.example.com" \
     --verbose \
     https://api.example.com/users
Check response headers:
Access-Control-Allow-Origin: https://app.example.com
Final Thoughts
CORS is not just a frontend 
issue — it is a critical API security layer.
A production-ready CORS 
strategy should:
Explicitly 
trust originsAvoid wildcardsRestrict methods and headersUse environment-specific configurationSupport secure credential handlingFollow correct middleware order
If configured properly, CORS becomes predictable, secure, and easy to maintain even in large enterprise systems.
Further reading:
ASP.NET Core Security Overview
MDN CORS Guide
Microsoft ASP.NET Core GitHub Repository
