Saturday, August 24, 2019

Enable Cross-Origin Requests (CORS) in ASP.NET Core

This article shows how to enable CORS in an ASP.NET Core app.
Browser security prevents a web page from making requests to a different domain than the one that served the web page. This restriction is called the same-origin policy
The same-origin policy prevents a malicious site from reading sensitive data from another site. Sometimes, you might want to allow other sites make cross-origin requests to your app. For more information, see the Mozilla CORS article.
  • Is a W3C standard that allows a server to relax the same-origin policy.
  • Is not a security feature, CORS relaxes security. An API is not safer by allowing CORS. For more information, see How CORS works.
  • Allows a server to explicitly allow some cross-origin requests while rejecting others.
  • Is safer and more flexible than earlier techniques, such as JSONP.

Same origin

Two URLs have the same origin if they have identical schemes, hosts, and ports (RFC 6454).
These two URLs have the same origin:
  • https://example.com/foo.html
  • https://example.com/bar.html
These URLs have different origins than the previous two URLs:
  • https://example.net – Different domain
  • https://www.example.com/foo.html – Different subdomain
  • http://example.com/foo.html – Different scheme
  • https://example.com:9000/foo.html – Different port
Internet Explorer doesn't consider the port when comparing origins.

CORS with named policy and middleware

CORS Middleware handles cross-origin requests. The following code enables CORS for the entire app with the specified origin:
C#
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddCors(options => { options.AddPolicy(MyAllowSpecificOrigins, builder => { builder.WithOrigins("http://example.com", "http://www.contoso.com"); }); }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseCors(MyAllowSpecificOrigins); app.UseHttpsRedirection(); app.UseMvc(); } }
The preceding code:
The AddCors method call adds CORS services to the app's service container:
C#
public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy(MyAllowSpecificOrigins,
        builder =>
        {
            builder.WithOrigins("http://example.com",
                                "http://www.contoso.com");
        });
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
For more information, see CORS policy options in this document .
The CorsPolicyBuilder method can chain methods, as shown in the following code:
C#
public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy(MyAllowSpecificOrigins,
        builder =>
        {
            builder.WithOrigins("http://example.com",
                                "http://www.contoso.com")
                                .AllowAnyHeader()
                                .AllowAnyMethod();
        });
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
The following highlighted code applies CORS policies to all the apps endpoints via CORS Middleware:
C#
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseHsts();
    }

    app.UseCors();

    app.UseHttpsRedirection();
    app.UseMvc();
}
See Enable CORS in Razor Pages, controllers, and action methods to apply CORS policy at the page/controller/action level.
Note:
  • UseCors must be called before UseMvc.
  • The URL must not contain a trailing slash (/). If the URL terminates with /, the comparison returns false and no header is returned.
See Test CORS for instructions on testing the preceding code.

Enable CORS with attributes

The [EnableCors] attribute provides an alternative to applying CORS globally. The [EnableCors]attribute enables CORS for selected end points, rather than all end points.
Use [EnableCors] to specify the default policy and [EnableCors("{Policy String}")] to specify a policy.
The [EnableCors] attribute can be applied to:
  • Razor Page PageModel
  • Controller
  • Controller action method
You can apply different policies to controller/page-model/action with the [EnableCors] attribute. When the [EnableCors] attribute is applied to a controllers/page-model/action method, and CORS is enabled in middleware, both policies are applied. We recommend against combining policies. Use the [EnableCors] attribute or middleware, not both in the same app.
The following code applies a different policy to each method:
C#
[Route("api/[controller]")] [ApiController] public class WidgetController : ControllerBase { // GET api/values [EnableCors("AnotherPolicy")] [HttpGet] public ActionResult<IEnumerable<string>> Get() { return new string[] { "green widget", "red widget" }; } // GET api/values/5 [EnableCors] // Default policy. [HttpGet("{id}")] public ActionResult<string> Get(int id) { switch (id) { case 1: return "green widget"; case 2: return "red widget"; default: return NotFound(); } } }
The following code creates a CORS default policy and a policy named "AnotherPolicy":
C#
public class StartupMultiPolicy { public StartupMultiPolicy(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddCors(options => { options.AddDefaultPolicy( builder => { builder.WithOrigins("http://example.com", "http://www.contoso.com"); }); options.AddPolicy("AnotherPolicy", builder => { builder.WithOrigins("http://www.contoso.com") .AllowAnyHeader() .AllowAnyMethod(); }); }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseHttpsRedirection(); app.UseMvc(); } }

Disable CORS

The [DisableCors] attribute disables CORS for the controller/page-model/action.

No comments:

Post a Comment

How to register multiple implementations of the same interface in Asp.Net Core?

 Problem: I have services that are derived from the same interface. public interface IService { } public class ServiceA : IService { ...