ASP.NET Core CORS WebAPI: no Access-Control-Allow-Origin header

41,251

Solution 1

Here is the answer to my own question, copied from the comments: I had not noticed that in Azure portal there is a CORS section. If I don't enter any allowed origin there, my code-based configuration seems to be totally irrelevant. This looks odd to me, as I'm forced to duplicate URLs here, but once I added * to the allowed origins there it worked.

Solution 2

I was facing similar error, but my error solved by keeping the pipeline in order. (startup.cs -> configureServices) like

  app.UseRouting();
  app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
  app.UseEndpoints(endpoints => .....

Solution 3

Adding the .AllowAnyHeader() method could fix your problem

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

Solution 4

The error message is very mis-leading. I was getting the same error after trying to add a new table to the DbContext. Angular was giving the no "Access-Control-Allow-Origin" error, but Postman was giving a 500 Internal Server error. The Login method was failing when trying to call _userManager.FindByEmailAsync(). Hope this helps someone else.

Share:
41,251
Naftis
Author by

Naftis

Updated on February 18, 2021

Comments

  • Naftis
    Naftis about 3 years

    I have deployed my ASP.NET Core web API to Azure, and I can access its endpoints using Swagger or a web debugger like Fiddler. In both cases (same origin in Swagger, different origin using Fiddler from my computer), when accessing the APIs I get the expected result, with CORS enabled as follows in my Startup.cs:

    1. add services.AddCors(); to ConfigureServices.

    2. add the middleware to Configure: I'm aware that order here matters (ASP.NET 5: Access-Control-Allow-Origin in response), so I am placing this call at the top of the method, only preceded by logging or diagnostic middleware; here is my full method:

    
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
        ILoggerFactory loggerFactory,
        IDatabaseInitializer databaseInitializer)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();
        loggerFactory.AddNLog();
    
        // to serve up index.html
        app.UseDefaultFiles();
        app.UseStaticFiles();
    
        // http://www.talkingdotnet.com/aspnet-core-diagnostics-middleware-error-handling/
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    
        // CORS
        // https://docs.asp.net/en/latest/security/cors.html
        app.UseCors(builder =>
                builder.WithOrigins("http://localhost:4200", "http://www.myclientserver.com")
                    .AllowAnyHeader()
                    .AllowAnyMethod());
    
        app.UseOAuthValidation();
        app.UseOpenIddict();
        app.UseMvc();
    
        databaseInitializer.Seed().GetAwaiter().GetResult();
        env.ConfigureNLog("nlog.config");
    
        // swagger
        app.UseSwagger();
        app.UseSwaggerUi();
    }
    

    The localhost CORS is used during development, and refers to an Angular2 CLI app. CORS is working fine locally, and my client and API apps are on different ports on the same localhost, so this is "true" cross origin (I'm remarking this because of the suggestions I found here: https://weblog.west-wind.com/posts/2016/Sep/26/ASPNET-Core-and-CORS-Gotchas: the author of the post notices that the CORS header in the response is sent only when actually required, i.e. in true cross-origin environments).

    Using Fiddler I can succesfully access the remote API, but I get NO Access-Control-Allow-Origin header. Thus, when calling the API from the browser (through my client app) the AJAX request fails, even if the server returns 200. Sample Fiddler request (success):

    GET http://mywebapisiteurl/api/values HTTP/1.1
    User-Agent: Fiddler
    

    response:

    HTTP/1.1 200 OK
    Transfer-Encoding: chunked
    Content-Type: application/json; charset=utf-8
    Server: Microsoft-IIS/8.0
    X-Powered-By: ASP.NET
    Set-Cookie: ARRAffinity=3d551180c72208c1d997584c2b6119cf44e3a55c868f05ffc9258d25a58e95b1;Path=/;Domain=prinapi.azurewebsites.net
    Date: Thu, 01 Dec 2016 10:30:19 GMT
    
    ["value1","value2"]
    

    When trying to access the remote API deployed on Azure, my client app always fails its AJAX request with error:

    No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.myclientserver.com' is therefore not allowed access.
    

    Here is a sample client code using Angular2 (using Plunker):

    import {Component, NgModule} from '@angular/core';
    import {BrowserModule} from '@angular/platform-browser';
    import { Http, Headers, Response } from '@angular/http';
    import { HttpModule } from '@angular/http';
    
    @Component({
      selector: 'my-app',
      template: `
        <div>
          <h2>Hello {{name}}</h2>
          <button (click)="test()">test</button>
        </div>
      `,
    })
    export class App {
      name:string;
      constructor(private _http: Http) {
        this.name = 'Angular2'
      }
      public test() {
        this._http.get('http://theapisiteurlhere/api/values',
        {
            headers: new Headers({
              'Content-Type': 'application/json'
            })
        })
        .subscribe(
          (data: any) => {
            console.log(data);
          },
          error => {
            console.log(error);
          });
      }
    }
    
    @NgModule({
      imports: [ BrowserModule, HttpModule ],
      declarations: [ App ],
      bootstrap: [ App ]
    })
    export class AppModule {}
    

    To sum up, it seems that the ASPNET API server is not returning the expected CORS headers, and thus my browser-based client hosted on a different origin fails. Yet, the CORS setup seems to be OK, at least judging from the documentation quoted above; I'm in true cross-origin environment; and I'm placing the middleware before the others. Maybe I'm missing something obvious, but googling around these are all the recommendations I found. Any hint?

    UPDATE

    In reply to @Daniel J.G: the request/response from fiddler are successful:

    GET http://theapiserver/api/values HTTP/1.1
    User-Agent: Fiddler
    Host: theapiserver
    Origin: http://theappserver/apps/prin
    

    and:

    HTTP/1.1 200 OK
    Content-Type: application/json; charset=utf-8
    Server: Microsoft-IIS/8.0
    Access-Control-Allow-Origin: http://theappserver/apps/prin
    X-Powered-By: ASP.NET
    Set-Cookie: ARRAffinity=3d551180c72208c1d997584c2b6119cf44e3a55c868f05ffc9258d25a58e95b1;Path=/;Domain=theapiserver
    Date: Thu, 01 Dec 2016 14:15:21 GMT
    Content-Length: 19
    
    ["value1","value2"]
    

    The request/response from Angular2 (Plunker) instead fail, as reported. By inspecting the network traffic, I can see the preflight request only:

    OPTIONS http://theapiserver/api/values HTTP/1.1
    Host: theapiserver
    Proxy-Connection: keep-alive
    Access-Control-Request-Method: GET
    Origin: http://run.plnkr.co
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36
    Access-Control-Request-Headers: content-type
    Accept: */*
    Referer: http://run.plnkr.co/h17wYofXGFuTy2Oh/
    Accept-Encoding: gzip, deflate, sdch
    Accept-Language: en-US,en;q=0.8,it;q=0.6
    
    HTTP/1.1 204 No Content
    Server: Microsoft-IIS/8.0
    X-Powered-By: ASP.NET
    Set-Cookie: ARRAffinity=3d551180c72208c1d997584c2b6119cf44e3a55c868f05ffc9258d25a58e95b1;Path=/;Domain=theapiserver
    Date: Thu, 01 Dec 2016 14:23:02 GMT
    

    After this, the request fails and no more traffic goes to the server. The reported issue is that Response to preflight request doesn't pass access control check, again because of lack of the header in the response:

    XMLHttpRequest cannot load http://theapiserver/api/values. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://run.plnkr.co' is therefore not allowed access.
    
  • ews2001
    ews2001 about 6 years
    The OP is asking about ASP.NET CORE, not ASP.NET
  • Naftis
    Naftis almost 6 years
    For interested readers, this is a newer minimal sample for the password flow using OpenIdDict rc 3, which got some API changes: github.com/Myrmex/oid-credentials. Pay attention to the [Authorize] attribute parameter (end note in readme).
  • Kien Chu
    Kien Chu almost 6 years
    I've not tested but if this is true, what's the point of having CORS config in the code? thanks Naftis for pointing it out :)
  • Ben Walters
    Ben Walters over 5 years
    You just saved me hours of troubleshooting! Thank you! I appreciate that MS is allowing CORS configuration in the Azure Portal, but it's frustrating that it's not more obvious. This seems to completely override the code-based CORS config (as others have said)...
  • Amorphis
    Amorphis over 5 years
    this is un neccessary., you can use app.UseCors
  • Devin Andres Salemi
    Devin Andres Salemi over 5 years
    I added * to allowed origins, but now my POST requests generate 500 errors, both in my Angular app and Postman tests
  • Andy
    Andy over 5 years
    This seems to be fixed now. I can leave the CORS section blank and it honors my application settings. What I was doing wrong was adding them like this http://www.example.com/, which is wrong. You have to add them like this: http://www.example.com (without the tailing forward-slash)
  • Subhasish
    Subhasish almost 4 years
    Oh God, I have spent last 7 days on this issue and finally this post saved me. Thanks a lot.
  • James Fleming
    James Fleming almost 3 years
    Thanks! that tip ended hours of head scratching & binge drinking!
  • captainblack
    captainblack over 2 years
    Congrulations! I have tried everything but that point saved me