tucaz
tucaz

Reputation: 6684

Handling CORS policy for multiple environment in ASP.NET Core 3.1

I'm trying to "toggle" between my CORS policies depending on the environment the application is running.

I have two policies declared as follows:

services.AddCors(options =>
{
    options.AddPolicy(CORSPolicies.PublicApi,
        builder => builder
            .AllowAnyHeader()
            .WithMethods("POST", "GET")
            .WithOrigins("https://domain1.com", "https://domain2.com"));

    options.AddPolicy(CORSPolicies.Dev,
        builder => builder
            .AllowAnyHeader()
            .AllowAnyMethod()
            .AllowAnyOrigin());
});

These policies should be only applicable to a few controllers so I'm using the attribute to apply them:

[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
[AllowAnonymous]
[EnableCors(CORSPolicies.PublicApi)]
public class PublicApiControllerBase : ControllerBase
{
}

PublicAPI policy should be valid for production where domains are going to actually be restricted. Dev policy allows anything since I'll be using it locally.

I tried to set the default policy to be Dev conditionally on the application start, but since EnableCorsAttribute overrides what is defined by app.UseCors() it didn't work as PublicApi policy will be used no matter what. Here's my naive attempt:

if (env.IsDevelopment())
{
    app.UseCors(CORSPolicies.Dev);
}
else
{
    app.UseCors();
}

How can I a) make my PublicApi policy behave differently depending on the environment my app is running or b) conditionally apply PublicApi or Dev policy depending on the environment?

Upvotes: 8

Views: 2773

Answers (1)

Kirk Larkin
Kirk Larkin

Reputation: 93003

For option A, you can inject IWebHostEnvironment into the Startup constructor, capture it as a field, and use it in ConfigureServices.

Here's what that looks like:

public class Startup
{
    private readonly IWebHostEnvironment env;

    public Startup(IWebHostEnvironment env)
    {
        this.env = env;
    }

    public void ConfigureService(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy(CORSPolicies.PublicApi, builder =>
            {
                if (env.IsDevelopment())
                {
                    builder.AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowAnyOrigin();
                }
                else
                {
                    builder.AllowAnyHeader()
                        .WithMethods("POST", "GET")
                        .WithOrigins("https://domain1.com", "https://domain2.com");
                }
            });
        });

        // ...
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // ...

        app.UseCors();

        // ....
    }
}

This uses a single CORS policy, CORSPolicies.PublicApi, which is configured according to the environment.

Upvotes: 8

Related Questions