10

My application is working fine in IE browser, But it's not working in Chrome browser due to CORS issue.

The issue is

Failed to load http://localhost:52487/api/Authentication/: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://localhost:4200' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

I am using angular 2 in front-end and using Asp.net core 1.0 in back-end. I have tried

This is my startup code

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy("AllowAll", p =>
        {
            p.AllowAnyOrigin()
            .AllowAnyHeader()
            .AllowAnyMethod();
        });
    });

    // Add framework services.
    services.AddMvc();
    // Add functionality to inject IOptions<T>
    services.AddOptions();
    // Add our Config object so it can be injected
    services.Configure<Data>(Configuration.GetSection("Data"));

    services.Configure<COCSettings>(Configuration.GetSection("COCSettings"));

    services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));

    AppSettings.ConnectionString = Configuration["Data:DefaultConnectionString"];

    // *If* you need access to generic IConfiguration this is **required**
    services.AddSingleton<IConfiguration>(Configuration);

    // Injecting repopsitories with interface
    AddServices(services);

    // Add Json options
    services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();
    app.UseMiddleware(typeof(ErrorHandling));
    app.UseMiddleware(typeof(GetNoCache));
    app.UseCors("AllowAll");
    app.UseMvc();
}

this is how I am calling the API from UI(angular) side

constructor(private http: Http) {
    this.headers = new Headers();
    this.headers.append('Accept', 'application/json');
}

GetMaintainCOC(FYONId) {
    return this.http.get(this.apiUrl + 'GetCertificationofConformity?FYONId=' + FYONId, { withCredentials: true })
    .map(responce => <any>responce.json())
    .catch(error => {
        return Observable.throw(error);
    });
}
Ramesh Rajendran
  • 37,412
  • 45
  • 153
  • 234
  • "tried some of the ... previous answers" - What did you try exactly? Did you try setting a white list like [this](https://stackoverflow.com/questions/42803394/cors-credentials-mode-is-include), what part of that solution did not work for you? – Tewr Feb 19 '18 at 07:32
  • Not sure what you are asking (it is clear what problem you have - you disagree with CORS policy - https://stackoverflow.com/questions/19743396/cors-cannot-use-wildcard-in-access-control-allow-origin-when-credentials-flag-i) - please clarify what you want to achieve... Sounds like not using Chrome is the only option (at least for some time till other browsers align with the same policy) as you explicitly `p.AllowAnyOrigin()`... – Alexei Levenkov Feb 19 '18 at 07:33
  • @Tewr Added withCredential true in `http.get()`. But I am didn't see any question related with this exact problem. So I have manually tried with some suggestions from stack overflow and google. – Ramesh Rajendran Feb 19 '18 at 07:35
  • `AllowAnyOrigin` just plain isn't going to work if you want this to work with credentials. So don't set that - specify specific origins. – Damien_The_Unbeliever Feb 19 '18 at 07:39
  • I got it. But i don't know is this exact solution. But it is working now in all browsers. :) Please check my answer :) – Ramesh Rajendran Feb 19 '18 at 07:40
  • 3
    @AlexeiLevenkov that's not exactly true, because `AllowAnyOrigin` does not necessary translate to `Access-Control-Allow-Origin: *`. ASP.NET knows that "*" cannot be used with credentials, so will use request origin instead if you specify `AllowCredentials`. – Evk Feb 19 '18 at 08:25

2 Answers2

14

It is working, when I am calling AllowCredentials() inside of AddPolicy

 services.AddCors(options =>
            {
                options.AddPolicy("AllowAll", p =>
                {
                    p.AllowAnyOrigin()
                    .AllowAnyHeader()
                    .AllowAnyMethod()
                    .AllowCredentials();
                });
            });

I got this key of idea from Access-Control-Allow-Origin: "*" not allowed when credentials flag is true, but there is no Access-Control-Allow-Credentials header

What I understood

I am using { withCredentials: true } in angular http service call. So I guess I should use AllowCredentials() policy in CORS service.

Ramesh Rajendran
  • 37,412
  • 45
  • 153
  • 234
2

Well you appear to have it solved, but here's the simple answer.

If you set the withCredentials flag in the request definition, cookies etc. will be passed in the request. Otherwise they won't be passed.

If your server returns any Set-Cookie response headers, then you must also return the Access-Control-Allow-Credentials: true response header, otherwise the cookies will not be created on the client. And if you're doing that, you need to also specify the EXACT origin in the Access-Control-Allow-Origin response header, since Access-Control-Allow-Origin: * is not compatible with credentials.

So do this:

  • Pass withCredentials in request
  • Pass Access-Control-Allow-Origin: <value-of-Origin-request-header> response header
  • Pass Access-Control-Allow-Credentials: true response header
roryhewitt
  • 4,097
  • 3
  • 27
  • 33