Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET Core UseCors() does not add headers

This would be a duplicate of How does Access-Control-Allow-Origin header work?, but the method there also isn't working for me. I'm hoping I'm just missing something.

I am trying to get a Access-Control-Allow-Origin header in my response from my .NET Core Web API, which I am accessing via AJAX.

I have tried several things. All, unless noted otherwise, have been in the Startup.cs file.

Method 1

As per the Microsoft Documentation:

public void ConfigureServices(IServiceCollection services) {     // Add database     services.AddDbContext<DbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DbConnection")));      // Add the ability to use the API with JSON     services.AddCors();      // Add framework services.     services.AddMvc(); }  public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) {     loggerFactory.AddConsole(Configuration.GetSection("Logging"));     loggerFactory.AddDebug();      if (env.IsDevelopment())     {         using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())         {             serviceScope.ServiceProvider.GetService<DbContext>().Database.Migrate();             serviceScope.ServiceProvider.GetService<DbContext>().EnsureSeedData();         }     }      app.UseCors(builder => builder.WithOrigins("https://localhost:44306").AllowAnyMethod());      app.UseJwtBearerAuthentication(new JwtBearerOptions     {         Authority = Configuration["Authentication:AzureAd:AADInstance"] + Configuration["Authentication:AzureAd:TenantId"],         Audience = Configuration["Authentication:AzureAd:Audience"],     });      app.UseMvc(); } 

Method 2

public void ConfigureServices(IServiceCollection services) {     // ...      services.AddCors(options => options.AddPolicy("AllowWebApp",         builder => builder.AllowAnyMethod()                           .AllowAnyMethod()                           .AllowAnyOrigin()));                           //.WithOrigins("https://localhost:44306")));      // ... }  public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) {     // ...      app.UseCors("AllowWebApp");      // ... } 

I've also tried adding [EnableCors("AllowWebApp")] on both the Controller and Method.

From Postman, I get:

content-encoding → gzip
content-type → text/plain; charset=utf-8
date → Wed, 25 Jan 2017 04:51:48 GMT
server →Kestrel
status → 200
vary → Accept-Encoding
x-powered-by → ASP.NET
x-sourcefiles → =?UTF-8?B?[REDACTED]

I've also tried it in Chrome, and gotten similar headers.

If it matters, the method I'm trying to access has an Authorize attribute on it. But that part should be working fine (I'm at least getting a good response)

So, am I missing something very obvious, or did this get broken? I'm currently running version 1.1.0.


Edit adding JS and Controller Stub

function getContactPreviews(resultsCallback) {     var xmlhttp = new XMLHttpRequest();      xmlhttp.onreadystatechange = () => {         if (xmlhttp.readyState == XMLHttpRequest.DONE && xmlhttp.status == 200) {             resultsCallback(JSON.parse(xmlhttp.response));         }     }      xmlhttp.open("GET", "https://localhost:44357/api/User/ContactsPreview", true);     xmlhttp.setRequestHeader("Authorization", "Bearer " + localStorage.getItem("AuthorizationToken"));     xmlhttp.send(); } 

Controller Stub

[Authorize] [Route("api/[controller]")] public class UserController : ApiController {     [HttpGet(nameof(ContactsPreview))]     [EnableCors("AllowWebApp")]     public IEnumerable<Customer> ContactsPreview()     {         // ...     } } 
like image 322
David Avatar asked Jan 25 '17 05:01

David


People also ask

How do I fix CORS header Access-Control allow Origin missing?

If the server is under your control, add the origin of the requesting site to the set of domains permitted access by adding it to the Access-Control-Allow-Origin header's value. You can also configure a site to allow any site to access it by using the * wildcard. You should only use this for public APIs.


2 Answers

The problem is that when using Bearer authentication (or any I would imagine), it adds a header "Authorization", and the server will only give an okay if the setup allows for that header.

There's two ways to solve the problem, and below is the only code needed. It goes in the Configure() method in Startup.cs in the Web API solution.

Method 1: Allow all headers

app.UseCors(builder => builder.WithOrigins("https://localhost:44306")                                 .AllowAnyMethod()                                 .AllowAnyHeader()); 

Method 2: Allow specific headers

app.UseCors(builder => builder.WithOrigins("https://localhost:44306")                               .AllowAnyMethod()                               .WithHeaders("authorization", "accept", "content-type", "origin")); 

The extra headers are because, per the documentation:

Browsers are not entirely consistent in how they set Access-Control-Request-Headers. If you set headers to anything other than "*", you should include at least "accept", "content-type", and "origin", plus any custom headers that you want to support.

like image 146
David Avatar answered Sep 24 '22 08:09

David


The Access-Control-Allow-Origin header is returned only if:

  1. The request includes an "Origin" header.
  2. The requested origin matches the CORS policy.

Then the server returns the ACAO-header with the origin URL as value.

The Origin header is usually set by the XMLHttpRequest object.

For more information, see How CORS works

like image 24
Luis Cantero Avatar answered Sep 26 '22 08:09

Luis Cantero