Cross-Origin Resource Sharing (CORS) is a standard in web applications that allows or restricts web pages from making requests to a domain different from the one that served the initial web page. Today we will explore how to implement and manage CORS in ASP.NET Core applications effectively.
How CORS works
When a web page makes a cross-origin HTTP request, the browser automatically adds an Origin
header to the request.
The server checks this header against its CORS policy.
If the origin is allowed, the server responds with a Access-Control-Allow-Origin
CORS header.
This indicates that the request is allowed to be served on the server.
The server doesn't return an error if the CORS policy doesn't allow the request to be executed. The client is responsible for returning error to the client and blocking the response.
CORS is a way for a server to allow web browsers to execute a cross-origin requests. Browsers without CORS can't do cross-origin requests.
When To Use CORS
CORS should be enabled in ASP.NET Core:
- To allow your API to be accessed from different domains
- When your frontend and backend are hosted separately
- To control specific resources in your application to be accessible from other domains
- In development mode
To enable CORS in ASP.NET Core, call the AddCors
method on the IServiceCollection
to add it to the DI container:
csharpbuilder.Services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", policyBuilder => policyBuilder.WithOrigins("http://example.com")); });
And add CORS to the middleware pipeline by calling UseCors
method:
csharpapp.UseCors("AllowSpecificOrigin");
Often CORS are enabled in ASP.NET Core apps only in the development mode to simplify development when frontend and backend are run on different hosts or ports. Consider using CORS in production only when it is absolutely required
Correct Order of Middlewares When Using CORS
Here are few important tips when placing UseCors
middleware:
UseCors
middleware should be placed beforeUseResponseCaching
due to this bug.UseCors
middleware should be placed beforeUseStaticFiles
to ensure CORS headers are properly added to the static file responses
csharpapp.UseCors(); app.UseResponseCaching(); app.UseStaticFiles();
Enable CORS in WebApi Controllers
To apply CORS policies to specific endpoints, use the RequireCors
method in endpoint routing configuration:
csharpapp.UseEndpoints(endpoints => { endpoints.MapControllers().RequireCors("AllowSpecificOrigin"); });
You can enable or disable CORS for a specific controller:
csharp[EnableCors("AllowSpecificOrigin")] public class UsersController : ControllerBase { // Controller methods } [DisableCors] public class ProductsController : ControllerBase { // Controller methods }
You can also enable or disable CORS for different controller methods:
csharppublic class UsersController : ControllerBase { [EnableCors("CorsPolicy1")] [HttpGet] public ActionResult<IEnumerable<string>> Get(Guid id) { var user = new User { Id = id, Name = "Anton" }; return Ok(user); } [EnableCors("CorsPolicy2")] [HttpPost] public ActionResult<IEnumerable<string>> Create(CreateUserRequest request) { return Ok(); } [DisableCors] [HttpDelete] public ActionResult<IEnumerable<string>> Create(Guid id) { return NoContent(); } }
Enable CORS in Minimal APIs
To enable CORS for minimal API endpoints simply call RequireCors
method for each endpoint:
csharpapp.MapGet("/api/books", () => { var books = SeedService.GetBooks(10); return Results.Ok(books); }).RequireCors("AllowAllOrigins");
CORS Policy Options
We already learned what the CORS is and how to enable it in the ASP.NET Core. It's time to explore what policy options does the CORS provide us:
- Set the allowed origins
- Set the allowed HTTP methods
- Set the allowed request headers
- Set the exposed response headers
- Credentials in cross-origin requests
Allowed Origin
Specify what origins are allowed to access the resource.
csharpbuilder.WithOrigins("http://example.com");
Allowed HTTP Methods
Define what HTTP methods can be used when accessing the resource.
csharpbuilder.WithMethods("GET", "POST", "PUT", "DELETE", "PATCH");
Allowed Request Headers
Specify headers that can be used when making the request.
csharpbuilder.WithHeaders("Content-Type", "Authorization");
Exposed Response Headers
Control which headers are exposed to the browser.
csharpbuilder.WithExposedHeaders("X-Custom-Header");
Credentials in Cross-Origin Requests
Determine if cookies should be included with requests.
csharpbuilder.AllowCredentials();
Allow Any Policy Options
There is a way to enable all policy options, for example for development:
csharpif (builder.Environment.IsDevelopment()) { builder.Services.AddCors(options => { options.AddPolicy("AllowAllOrigins", policyBuilder => policyBuilder.AllowAnyHeader() .AllowAnyMethod() .AllowAnyOrigin() //.AllowCredentials() .SetIsOriginAllowed(_ => true) ); }); } // ... if (app.Environment.IsDevelopment()) { app.UseCors("AllowAllOrigins"); }
NOTE: you can't use AllowAnyOrigin (wild card, allowing all origins) with AllowCredentials at the same time
Summary
Implementing CORS in ASP.NET Core is essential for modern web applications to securely manage cross-origin requests in the web browsers. You can configure CORS for controllers and minimal APIs. You can use CORS in development mode to simplify your frontend and backend development. Use CORS in production mode only when it is absolutely required.
Hope you find this blog post useful. Happy coding!