Search code examples
asp.net-coreiiscorsfiddlerpreflight

CORS preflight request doesn't hit IIS until fiddler is working


Yes, it's another CORS question, I have searched for more than three days for this problem trying to understand what is happening.

The sample application found under this repo Sample Application

  • I'm using ASP.net Core 2.2 hosted in local IIS with Windows Authentication enabled and Anonymous Authentication disabled. configured to allow CORS.

     services.AddCors(options =>
            {
                options.AddPolicy("AllowOrigin",
                    builder => builder               
                              .SetIsOriginAllowed(origin => true)                        
                              .AllowAnyMethod()
                              .AllowAnyHeader()
                              .AllowCredentials()
                );
            });
    
  • For handling preflight request I have created custom middleware

    private Task BeginInvoke(HttpContext context)
        {
            if (context.Request.Method == "OPTIONS")
            {
                if (!string.IsNullOrEmpty( context.Request.Headers["Origin"]) )
                    context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)context.Request.Headers["Origin"] });
                context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "foo,Access2, Origin, X-Requested-With, Content-Type, Accept,authentication" });
                context.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "GET, POST, PUT, DELETE, OPTIONS" });
                context.Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
    
    
                context.Response.StatusCode = 200;
                return Task.CompletedTask; //context.Response.WriteAsync("OK");
            }          
            return _next.Invoke(context); //complete request pipline 
        }
    
  • When I try to send a complex request with a customer header (preflight request) (Request A)

    fetch('http://localhost:8050/api/values',{credentials:'include', headers:{'foo':'foo'}})
    .then(response => response.json())
    .then(data => console.log(data));
    

I got an error

Error from console

This how the request be in the fiddler, (for your information this request doesn't reach ASP.Net App and just hit IIS)

error from fiddler

  • The most interesting thing when activate fiddler then create a simple get request from the browser(chrome) to the endpoint('http://localhost:8050/api/values), It will produce three authentication handshake and succeeded
  1. => 401
  2. => 401
  3. => 200

As shown in fiddler (it's 3 request authentication handshake

  • Then if I try the complex request (Request A) again (that caused an error the first time) it goes without any problem as two requests
  1. A preflight request (OPTIONS verb) with the response of 200 (succeded)
  2. The actual request (GET verb) with the required response of 200 (succeded)

Here the fiddler analysis complex request successed

My Question

  1. Why a simple get request (from chrome) while activating fiddler solve all my problem and allow me after that to make any complex CORS request without any error.
  2. How I can make a complex CORS request without any problem (without needing a fiddler).

Note that I'm thinking in (can be wrong) Fiddler acts as a proxy that deals with the IIS and can make the required authentication handshake after that IIS accept any complex request.

The sample application found under this repo Sample Application


Solution

  • I have found the solution to my problem: as Lex Li suggest it's about the IIS CORS module

    CORS in IIS When deploying to IIS, CORS has to run before Windows Authentication if the server isn't configured to allow anonymous access. To support this scenario, the IIS CORS module needs to be installed and configured for the app.

    By installing the IIS CORS module from IIS CORS Module

    For IIS CORS module documentation IIS CORS documentation

    Thanks Lex Li for your support