Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP .NET Core use multiple CORS policies

I am trying to setup 2 CORS policies. One as an api default and the other to use on Controllers as I need them. The reason I want to do this is because I have an endpoint that takes in an object with email info and sends an email (to use with the contact me box on my webpage) and have it only accept requests from my domain.

My startup.cs file snippet:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddPolicy("Example",
                    builder => builder.WithOrigins("http://www.example.com"));
                options.AddPolicy("AllowAll",
                    builder => builder.AllowAnyOrigin());
            });

            services.AddMvc();
            //other configure stuff
        }


 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseCors(builder =>
        {
            builder.AllowAnyHeader();
            builder.AllowAnyMethod();
            builder.WithOrigins("AllowAll");
        });

        app.UseMvcWithDefaultRoute();
    }

My emailcontroller.cs file:

using System.Threading.Tasks;
using MyAPI.Models;
using MyAPI.Services;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;

namespace MyAPI.Controllers
{
    [Produces("application/json")]
    [Route("api/Email")]
    [EnableCors("Example")]
    public class EmailController : Controller
    {
        private readonly IEmailSender _emailSender;

        public EmailController(IEmailSender emailSender)
        {
            _emailSender = emailSender;
        }

        [HttpPost]
        public async Task Post([FromBody] Email email)
        {
            await _emailSender.SendEmailAsync(email);
        }
    }

}

Javascript used to send email:

function sendEmail(email)
{
    var urlToApi = "http://<ipToApi>:5000/api";
    $.ajax({
            method: "POST",
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify(email),     
            url: urlToApi + "/email/",
            success: function(data) {  
                console.log(data);
                console.log('probably sent');
            },
            error: function(jqXHR, textStatus, errorThrown){
                console.log(textStatus);
                alert("There was like, an error doing that");
            }
        });
}

This is what I get trying to send from http://www.example.com

XMLHttpRequest cannot load http://<ipToApi>:5000/api/email/. 
Response to preflight request doesn't pass access control check: 
No 'Access-Control-Allow-Origin' header is present on the requested
 resource. Origin 'http://www.example.com' is therefore not allowed access.

EDIT

This works:

services.AddCors(options =>
            {
                options.AddPolicy("Example",
                    builder => builder.WithOrigins("http://www.example.com")
                                        .AllowAnyHeader()
                                        .AllowAnyMethod());
                options.AddPolicy("AllowAll",
                    builder => builder.AllowAnyOrigin()
                                        .AllowAnyHeader()
                                        .AllowAnyMethod());
            });
like image 352
Jrow Avatar asked May 15 '17 17:05

Jrow


People also ask

How do I allow all CORS in net core?

There are three ways to enable CORS: In middleware using a named policy or default policy. Using endpoint routing. With the [EnableCors] attribute.

What is CORS policy in .NET core?

CORS means cross-origin resource sharing. You'll see more in just a minute, but in a nutshell, CORS is a mechanism—an HTTP protocol, to be exact—that allows web applications to access resources hosted on different domains (or origins.)


2 Answers

Configure Method

app.UseRouting();
app.UseCors("CorsApi");
app.UseAuthentication();

ConfigureServices method

services.AddCors(options =>
    {
        options.AddPolicy("CorsApi",
            builder => builder.WithOrigins("http://localhost:4200", "http://mywebsite.com")
        .AllowAnyHeader()
        .AllowAnyMethod());
    });
like image 66
tfa Avatar answered Oct 24 '22 10:10

tfa


To set a default CORS policy use app.UseCors(string policyName) overload.

Your CORS requests will be failing because you are rejecting all headers and methods. From what I read, the CORS specification states that you shouldn't set any headers at all if any of the checks fail. See implementation here, this is most likely why your client will be receiving the standard No 'Access-Control-Allow-Origin' header is present error, as no headers are added at all, even though the Origin check passes.

The following should work as expected, and your [EnableCors(...)] decorator should override the default!

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy("Example",
            builder => builder.WithOrigins("http://www.example.com")
                                .AllowAnyHeader()
                                .AllowAnyMethod());
        options.AddPolicy("AllowAll",
            builder => builder.AllowAnyOrigin()
                                .AllowAnyHeader()
                                .AllowAnyMethod());
    });

    services.AddMvc();
    //other configure stuff
}


public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseCors("AllowAll"); //Default

    app.UseMvcWithDefaultRoute();
}

You may need to add .AllowCredentials() to your policies, but I am not sure. Read here perhaps?

like image 11
Mardoxx Avatar answered Oct 24 '22 09:10

Mardoxx