aspnet / CORS

[Archived] Implementations of common CORS policy and CORS middleware. Project moved to https://github.com/aspnet/AspNetCore
Apache License 2.0
90 stars 46 forks source link

The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed #129

Closed Tratcher closed 7 years ago

Tratcher commented 7 years ago

From @helderboone on October 9, 2017 14:30

I created an angular 1 app which consumes an RESTfull web service (asp net core 1.1).

I have enabled CORS with the following settings:

Startup.cs

 public void ConfigureServices(IServiceCollection services)
        {
        services.AddCors(options => options.AddPolicy("AllowAll", p => p.AllowAnyOrigin().AllowAnyMethod().WithHeaders("accept", "content-type", "authorization")));        

            var mvc = services.AddMvc();

            mvc.AddFeatureFolders();
    }

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            app.UseForwardedHeaders(new ForwardedHeadersOptions
            {
                ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
            });

            loggerFactory.AddConsole(Configuration.GetSection("Logging")).AddDebug();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
            }
            else
            {
                app.UseExceptionHandler("/home/error");
            }

            app.UseCors("AllowAll");
      }

MetaController.cs

    [Route("[controller]/v1/[action]")]
    [Produces("application/json")]
    [EnableCors("AllowAll")]
    public class MetaController : Controller
    {   }

The angular http method call

 $http({
                    method: 'POST',
                    url: 'https://www.mydomain.com/api/v1/meta/',
                    data: data,
                    headers:
                    {
                        'Content-Type': 'application/json',
                        'Authorization': 'Basic mytoken'
                    }
                })

Any thoughts?

Copied from original issue: aspnet/Home#2237

Tratcher commented 7 years ago

What does a Fiddler trace of the headers show?

helderboone commented 7 years ago

I have to point out something. It weirdly sending two request clicking save button. The first gives the error that i described above with the following reponse headers:

Access-Control-Allow-Headers:DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization
Access-Control-Allow-Methods:GET, POST, OPTIONS
Access-Control-Allow-Origin:*
Access-Control-Max-Age:1728000
Connection:keep-alive
Content-Length:0
Content-Type:application/json charset=UTF-8
Date:Mon, 09 Oct 2017 14:14:00 GMT
Server:nginx/1.10.3 (Ubuntu)

The second request effectively works out storing the data with the following headers:

Access-Control-Allow-Headers:DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization
Access-Control-Allow-Methods:GET, POST, OPTIONS
Access-Control-Allow-Origin:*
Access-Control-Allow-Origin:*
Connection:keep-alive
Content-Type:application/json; charset=utf-8
Date:Mon, 09 Oct 2017 14:14:03 GMT
Location:http://www.mydomain.com/foo?Length=0
Server:nginx/1.10.3 (Ubuntu)
Transfer-Encoding:chunked
helderboone commented 7 years ago

@Tratcher I just made a request through Fiddler and works out with the following headers: Headers sent to the server:

User-Agent: Fiddler
Content-Type: application/json
Authorization: Basic mytoken
Accept: application/json
Host: www.mydomain.com
Content-Length: 148

Header sent from the server:

HTTP/1.1 201 Created
Server: nginx/1.10.3 (Ubuntu)
Date: Mon, 09 Oct 2017 14:56:44 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Location: http://www.mydomain.com/meta?Length=0
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization
helderboone commented 7 years ago

@Tratcher I thought that the issue could be caused by the app itself. But i created a test using Jquery in order to validate this and it sends two request on browser. So it seems that the first is pre flight request and the second the actual request. The problem is happening on pre flight request ( i suspect).

$("#sendData").click(function (e) {
            e.preventDefault();
            $.ajax({
                type: "POST",
                headers: {
                    'Authorization': 'Basic mytoken',                    
                    'Content-Type': 'application/json'
                },
                url: 'https://mydomain.com/api/foo',
                data: data,                
                dataType: "json",        
                success: function (response) {
                    console.log(response);
                }
            });    
        });
Tratcher commented 7 years ago

@jbagga can you take a look?

jbagga commented 7 years ago

@helderboone Is your issue that Access-Control-Allow-Origin header has a value of "*" but your origin is not getting access?

Also I noticed you are trying to use a controller but do not have app.UseMvc()? Did you just not copy that over?

jbagga commented 7 years ago

@helderboone I tried your scenario but cannot repro with 1.1 or 2.0.

For trying out 1.1.0 you can use the sample here.

For trying out 2.0.0 you can use the sample here.

If you are using 1.1 and need to continue using it, could you please clarify the issue? Are you seeing " , " in Access-Control-Allow-Origin header instead of "*"?

jbagga commented 7 years ago

Closing for now as it cannot be reproduced.

@helderboone Please feel free to reopen the issue if you run into it again with a repro sample. The samples above should provide a starting point.

helderboone commented 7 years ago

@jbagga Regarding your first question i use app.UseMvcWithDefaultRoute(); I should metion that i have been using nginx as reverse proxy and the following settings:

server {
    listen 80;
    server_name mydomain.com www.mydomain.com;
    location / {
       if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Cache-Control,Content-Type,Authorization';
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'application/json charset=UTF-8';
        add_header 'Content-Length' 0;
        return 204;
     }

     if ($request_method = 'POST') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Content-Type,Authorization';
     }

     if ($request_method = 'GET') {

        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
     }

        proxy_pass http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection keep-alive;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Running locally there seems to be no issue since the application is running on kestrel. But using nginx as reverse proxy i have got this issue. I'm not saying the problem is nginx.

helderboone commented 7 years ago

@Tratcher I updated my question from original issue https://github.com/aspnet/Home/issues/2237. Could you update my question in this issue too because i can't edit?

Tratcher commented 7 years ago

@helderboone post your modified question as a comment.

thiagomajesk commented 7 years ago

@jbagga Does those samples work only for localhost (Kestrel) or should they work (as is) with Nginx as a reverse proxy too? Do I need to make any extra configs regarding Nginx (like @helderboone's) or not? If yes, what configs? I'm asking because the docs are not explicit about this and I'm having pretty much the same problem as @helderboone.

jbagga commented 7 years ago

@helderboone Have you tried it without the CORS headers in your conf file? UseCors enables the CORS middleware in your ASP.NET Core which should take care of these headers. So you can either have nginx do CORS or your ASP.NET Core app do CORS.

@thiagomajesk It should work as is without extra configs. Have you tried just using CORS (https://docs.microsoft.com/en-us/aspnet/core/security/cors) in ASP.NET Core app and just reverse proxying with nginx (no CORS settings)? If you still have an issue, please share a working sample, explain the error you see and I will take a look again!

thiagomajesk commented 7 years ago

@jbagga Thanks for the explanation. I'll definitely validate that. That's it, for now at least. Thanks again for the clarification :)