6

Yesterday I managed to have my API working on my local computer, however today (same code) on another computer, it's not working, I am getting this error on the console:

Failed to load http://localhost:52056/api/task: The 'Access-Control-Allow-Origin' header has a value 'null' that is not equal to the supplied origin. Origin 'null' is therefore not allowed access.

Here is the http request and response on Chrome:

enter image description here

(I don't see errors in IE/Firefox)

Here is my startup class (using .net core 2)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using TodoApi;

namespace TestCors
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<ITaskWarehouse, TaskWarehouse>();

            services.AddCors();
            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseCors(builder => builder
                    .AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .AllowCredentials());
            app.UseMvc();
        }
    }
}

What is wrong here? The code is the same from yesterday, however I was running on Windows 10 and this machine has Windows 7. Any thoughts? Thanks

Liam
  • 27,717
  • 28
  • 128
  • 190
TiagoM
  • 3,458
  • 4
  • 42
  • 83
  • Are you just opening html page which makes ajax request in browser, without any server (so by double-clicking on it)? – Evk Mar 15 '18 at 13:17
  • [A `null` `Access-Control-Allow-Origin` is a known exploit](https://security.stackexchange.com/questions/145326/how-did-the-facebook-originull-vulnerablity-of-access-control-allow-origin-null) so I'm guessing chrome has done the right thing and patched it where as the other browsers haven't (yet). What you change this to depends on what you actually want this to do. I would guess you want `*` which is a valid value – Liam Mar 15 '18 at 13:24
  • Hi @Evk, yes I am just double clicking on the html file in my disk file, it has javascript code to make the http request, using a javascript framework library (backbone).Is that a problem? – TiagoM Mar 15 '18 at 13:26
  • How do I make it to have * instead of null @Liam ? I configured AllowAnyOrigin on the configure method of the web api, shouldn't this be enough to have * on response instead of null ? – TiagoM Mar 15 '18 at 13:27
  • I'm not sure TBH, I don't use this technology, [maybe `WithOrigins("*")`](https://stackoverflow.com/a/44379971/542251) but that's a guess TBH – Liam Mar 15 '18 at 13:29

2 Answers2

8

Try removing

.AllowCredentials()

CORS doesn't allow you to have .AllowCredentials() AND .AllowAnyOrigin() for the same policy. I don't why it worked on a different machine.

This is from ASP.NET page

The CORS spec also states that setting origins to "*" is invalid if SupportsCredentials is true.

Liam
  • 27,717
  • 28
  • 128
  • 190
Simply Ged
  • 8,250
  • 11
  • 32
  • 40
  • This worked, thank you so much! The other machine had a different OS and also different chrome version, maybe it made things working somehow xD – TiagoM Mar 15 '18 at 13:42
  • 1
    CORS doesn't allow this yes, but asp.net core is smart enough to handle it. If you specify both - it will return request origin instead of "*" in response header (just like on screenshot in question). – Evk Mar 15 '18 at 13:57
2

The problem is your are opening html page which makes this request by just double clicking on it, without using a server. So url in your browser is "file:///...". That means there is no origin, and as you see on screenshot from your question - CORS request has "Origin: null" header. Different browsers handle this siutation differently. Chrome restricts cross-origin requests from such origin, even if response allows it (via returning "null" as "Access-Control-Allow-Origin").

So to fix - use proper server (local one), or use another browser for development. Also some people claim that starting chrome like this

chrome.exe --allow-file-access-from-files

Should also "fix" this, though I didn't try myself.

Update: I was under impression that even with Access-Control-Allow-Origin: * chrome will not allow it, but your comment on other answer seems to claim otherwise (by removing AllowCredentials() you made response to use "*" as allowed origin instead of origin provided in request). If so - that's another way to fix it (not sure, maybe it behaves differently in different chrome versions though).

Evk
  • 98,527
  • 8
  • 141
  • 191
  • Yes my browser is using "file:///...", can I just make you a quick question? If I only need to run this html file, what's the benefits of using a proper server (local one) ? Should I use nodejs only to serve this single html ? – TiagoM Mar 15 '18 at 13:34
  • 1
    @TiagoM well in this case it ensures that your CORS requests will work in chrome :) I just somehow didn't ever distributed raw html files to customers, but when I think about that - why not indeed. On the other hand you lose all benefits of web, such as effortless updates (I mean if you run not local but regular remote http server). So, depends on your scenario. – Evk Mar 15 '18 at 13:36
  • Makes sense, since this is just a simple exercise for an interview, I was not going through all the mess of configuring a proper server, but maybe I should do it for best practices, is nodejs easy to configure just to serve an html page? I mean, I still have to configure all the routes and so on I guess? – TiagoM Mar 15 '18 at 13:42
  • 1
    You can use this question to see how to run nodejs for single file: https://stackoverflow.com/q/35995273/5311735. Easy enough. But why not serve html file from the same server you use for api (localhost:56052)? As a bonus you will have no CORS problems. – Evk Mar 15 '18 at 14:12
  • Thanks for the link, I will check that out! That's something I though too, but since I am using typescript/webpack from command line, I though it would be over kill to join visual studio to the mix lol. – TiagoM Mar 15 '18 at 14:36