Cross-Origin Requests (CORS) in ASP.NET Core Web API
This blog is going to explain what a Cross Origin Request (CORS) is and how to implement it in ASP.NET Core web API. When a web page tries to access resources from a different webpage it is blocked by the browser security feature. This feature is called the Same Origin Policy (SOP). In many cases the developer has to access resources of different origins. In such cases CORS helps to relax the Same Origin Policy.
There are 3 ways to enable CORS in ASP.NET core.
- Middleware (name policy or default policy)
- Endpoint routing
- [EnableCORS] attribute
Let’s see that with the example.
Imagine you have an API which returns some JSON values. It’s URL is https://localhost:44351/api/Home. When trying to access another domain URL(https: // localhost: 44389 /) from the client page, it will give you the following error message.
Access to XMLHttpRequest at 'https://localhost:44351/api/Home' from origin 'https://localhost:44389' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
It happens because of the Same Origin Policy(SOP). To relax this same origin policy, you have to enable the Cross-Origin Requests (CORS) in the API. Let’s look at it one by one
Middleware
Default policy
To enable the CORS default policy, first you have to add the AddCors extension in the Startup.cs ConfigureServices() method in your API.
In the below code you can see that AddCors() is added to the service. And in the option, the default policy has been added. In the builder "https://localhost:44389" the URL has been whitelisted.
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddCors( options => options.AddDefaultPolicy( builder => builder.WithOrigins("https://localhost:44389") .AllowAnyMethod() .AllowAnyHeader() )); }
Next you need to add app.UseCors() middleware to the Configure() method. You must add CORS middleware before the UseRouting() middleware and after the UseAuthorization() middleware.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... ... ... app.UseRouting(); app.UseCors(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
Preflight
For some CORS requests, the browser first sends the preflight request to the API. The preflight request will contain the metadata of the original request. So the API server checks the metadata and responds to the priority request, declaring whether or not it can send a response to the original request.
The following is a original request header
Original Header Requestauthority: localhost:44351 :method: GET :path: /api/Home?_=1626359605790 :scheme: https accept: */* accept-encoding: gzip, deflate, br accept-language: en-US,en;q=0.9 content-type: application/json; charset=utf-8 origin: https://localhost:44389 referer: https://localhost:44389/ sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91" sec-ch-ua-mobile: ?0 sec-fetch-dest: empty sec-fetch-mode: cors sec-fetch-site: same-site user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
Original Response
In the response you can see the
access-control-allow-origin: https://localhost:44389. This means the
URL is whitelisted.
access-control-allow-origin: https://localhost:44389 content-length: 19 content-type: application/json; charset=utf-8 date: Thu, 15 Jul 2021 14:36:13 GMT server: Microsoft-IIS/10.0 x-powered-by: ASP.NET
Named Policy
Another method of enabling CORS via middleware is the named policy. In the below code you can see that the name ‘SamplePolicy’ has been added to the AddPolicy() method and added the "https://localhost:44389" URL to the WithOrigins() method.public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddCors( options => options.AddPolicy("SamplePolicy", builder => builder.WithOrigins("https://localhost:44389") .AllowAnyHeader() .AllowAnyMethod()) ); }
In the configure method, you have to pass the policy name "SamplePolicy" as a parameter in the app.UseCors() middleware. So it will enable the CORS.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... ... ... app.UseRouting(); app.UseCors("SamplePolicy"); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
Endpoint Routing
With endpoint routing you can enable the CORS to different endpoints using the RequireCors() extension.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... ... ... app.UseRouting(); app.UseCors(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers().RequireCors("SamplePolicy"); }); }
Enable CORS with attributes
The following is an example of how to enable CORS using the EnableCors attribute. Here the attribute is added at the Controller level. It therefore enables CORS for all methods within the system.
[EnableCors("SamplePolicy")] [Route("api/[controller]")] [ApiController] public class HomeController : Controller { [HttpGet] public List<string> Get() { return new() { "value1", "value2"}; } }
Also, you can enable CORS at the method level also. So, You can add different CORS policies for each method.
[Route("api/[controller]")] [ApiController] public class HomeController : Controller { [EnableCors("SamplePolicy1")] [HttpGet] public List<string> Get() { return new() { "value1", "value2"}; } [EnableCors("SamplePolicy2")] [HttpGet] public List<string> GetValue() { return new() { "value3", "value4"}; } }
I hope this helps you. Keep coding.
Comments
Post a Comment