Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.Net Core Configure CORS to allow all subdomains and all localhost ports at the same time

I would like to allow CORS requests to a common internal API from all internal websites (*.myintra.net) and also from all localhost ports (for when we are debugging various apps locally in IIS Express, i.e. http://localhost:12345, http://localhost:54321, etc).

This answer shows me how to use SetIsOriginAllowedToAllowWildcardSubdomains() to allow all subdomains.

This answer shows me how to allow any localhost port by using a SetIsOriginAllowed() delegate function.

However, it seems that these options do not work together. My configuration:

private bool AllowLocalhost(string origin)
{
    var uri = new Uri(origin);
    return (uri.Host == "localhost");
}

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        string[] corsList = "https://*.myintra.net,https://some.specificurl.com".Split(",");
        options.AddPolicy("CorsPolicy", builder =>
        {
            builder
            .WithOrigins(corsList.ToArray())
            .SetIsOriginAllowedToAllowWildcardSubdomains()
            .SetIsOriginAllowed(origin => AllowLocalhost(origin)) // disallows calls from myapp.myintra.net since it doesn't uri.Host match "localhost"
            ...();
        });
    });
    ...
}

I can swap the order of the configuration:

.SetIsOriginAllowed(origin => AllowLocalhost(origin))
.SetIsOriginAllowedToAllowWildcardSubdomains()

But then the AllowLocalhost() function is never called. I suppose it makes sense that only one works at a time, since the first check may return true, only to have the second one return false.

Ideally, I'd like a solution that doesn't involve me having to reimplement the allow wildcard logic inside of my AllowLocalhost() function.

Also worth noting that I really only need this in a development environment. Production would need to allow wildcards, but disallow localhost no matter the port.

like image 511
djs Avatar asked Oct 16 '22 05:10

djs


1 Answers

That's the way I implemented it:

I'm checking the origin with the IsOriginAllowed:

    public void ConfigureServices(IServiceCollection services)
    {
        // ...

        services.AddCors(options =>
        {
            options.AddPolicy(name: "AllowedCorsOrigins",
                builder =>
                {
                    builder
                        .SetIsOriginAllowed(IsOriginAllowed)
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                });
        });
        // ...

Activate Cors as always:

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
        {
        // ...
        app.UseCors("AllowedCorsOrigins");
        // ...

That's the method, that should do the trick. Accept all requests from example.com and another-example.com including all subdomains. And if the ASPNETCORE_ENVIRONMENT the Service is running contains "DEV" than also allow localhost.

private static bool IsOriginAllowed(string origin)
{
    var uri = new Uri(origin);
    var env = System.Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "n/a";

    var isAllowed = uri.Host.Equals("example.com", StringComparison.OrdinalIgnoreCase)
                    || uri.Host.Equals("another-example.com", StringComparison.OrdinalIgnoreCase)
                    || uri.Host.EndsWith(".example.com", StringComparison.OrdinalIgnoreCase)
                    || uri.Host.EndsWith(".another-example.com", StringComparison.OrdinalIgnoreCase);
    if (!isAllowed && env.Contains("DEV", StringComparison.OrdinalIgnoreCase))
        isAllowed = uri.Host.Equals("localhost", StringComparison.OrdinalIgnoreCase);

    return isAllowed;
}
like image 70
Kay Meister Avatar answered Oct 28 '22 13:10

Kay Meister