100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
C#

CORS Configuration

Understand how Cross-Origin Resource Sharing works in ASP.NET Core and how to configure it safely for browser-based clients calling your API.

SecurityIntermediate8 min readJul 10, 2026
Analogies

What CORS Actually Protects Against

CORS is a browser-enforced security mechanism, not a server-side firewall — it exists because browsers, by default, block JavaScript running on one origin (scheme + host + port) from reading responses from a different origin, to prevent a malicious site from silently using a logged-in user's cookies to read data from another site (like their bank). The server opts specific origins into cross-origin access by returning Access-Control-Allow-Origin and related headers; the browser, not your API, is the one that actually enforces the restriction by blocking the JavaScript from accessing the response if the headers don't match.

🏏

Cricket analogy: CORS is like a stadium's away-team dressing room policy — the browser is the security guard who, by default, won't let a visiting team's staff (a foreign origin's script) into the home dressing room unless the home ground explicitly issues them a pass (Access-Control-Allow-Origin).

Configuring the CORS Middleware

You register CORS with builder.Services.AddCors(options => options.AddPolicy("AllowFrontend", policy => policy.WithOrigins("https://app.example.com").AllowAnyMethod().AllowAnyHeader())), then apply it with app.UseCors("AllowFrontend") placed after UseRouting and before UseAuthorization in the middleware pipeline. Policies can be applied globally via app.UseCors() with a default policy, or scoped per-endpoint with [EnableCors("PolicyName")] and [DisableCors] for exceptions, and you can allow credentials (cookies, Authorization headers) with AllowCredentials(), but only in combination with explicitly listed origins — never with AllowAnyOrigin().

🏏

Cricket analogy: Defining a named CORS policy like 'AllowFrontend' is like a ground curator issuing a specific access list naming exactly which broadcast trucks (origins) can plug into the stadium's feed, rather than leaving the gate open to any truck that shows up.

Preflight Requests

For 'non-simple' requests — those using methods other than GET/HEAD/POST, or with custom headers like Authorization or Content-Type: application/json — the browser first sends an OPTIONS preflight request asking the server which methods and headers are allowed for that origin, before sending the actual request. ASP.NET Core's CORS middleware automatically intercepts and responds to these OPTIONS requests based on the matching policy, returning 204 with Access-Control-Allow-Methods and Access-Control-Allow-Headers; if the actual request's method or headers aren't covered by the policy, the browser blocks the real request from ever being sent.

🏏

Cricket analogy: A preflight OPTIONS request is like a team manager calling the match referee before the game to confirm which substitutions and equipment are allowed, so nobody wastes time attempting something that will be disallowed on the field.

csharp
// Program.cs
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowFrontend", policy =>
    {
        policy.WithOrigins("https://app.example.com", "https://staging.example.com")
              .AllowAnyMethod()
              .WithHeaders("Content-Type", "Authorization")
              .AllowCredentials();
    });
});

var app = builder.Build();

app.UseRouting();
app.UseCors("AllowFrontend");
app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

// A single endpoint override
[EnableCors("AllowFrontend")]
[HttpGet("public-stats")]
public IActionResult GetPublicStats() => Ok(_statsService.GetSummary());

Never combine .AllowAnyOrigin() with .AllowCredentials() — ASP.NET Core will throw an exception at startup because it's a well-known security hole: it would let any website silently make authenticated, cookie-carrying requests to your API on behalf of a logged-in user.

CORS only protects browser-based JavaScript callers. It does nothing to stop server-to-server requests, curl, Postman, or mobile apps, since those clients don't enforce the same-origin policy at all — CORS is not a substitute for authentication and authorization.

  • CORS is enforced by the browser, not the server — the API just supplies headers telling the browser what to allow.
  • AddCors with named policies configures allowed origins, methods, and headers; UseCors applies the policy in the pipeline.
  • UseCors must be placed after UseRouting and before UseAuthorization for endpoint-specific policies to resolve correctly.
  • Non-simple requests trigger a browser-issued OPTIONS preflight that the CORS middleware answers automatically.
  • AllowCredentials() requires explicitly listed origins and can never be combined with AllowAnyOrigin().
  • [EnableCors]/[DisableCors] let you override the default policy for specific controllers or actions.
  • CORS does not protect against non-browser clients — it must be paired with real authentication and authorization.

Practice what you learned

Was this page helpful?

Topics covered

#ASPNETCoreStudyNotes#MicrosoftTechnologies#CORSConfiguration#CORS#Configuration#Actually#Protects#StudyNotes#SkillVeris#ExamPrep