HTTP CORS requests with credentials are failing using Axios

Viewed 5957

I have a legacy webforms asp.net website and a new asp.net core site sharing an auth cookie. When I try to make a CORS HTTP request from Typescript (in the core site) to a Web Service method (in the legacy site) using Axios it fails unless I pass an empty data object. For example:

This request will fail:

    const url: string = "http://legacy.mydev.machine:1259/MyService.asmx/GetInformation";
    const optionsThatWontWork: AxiosRequestConfig = {
        withCredentials: true
    };
    axios.get(url, optionsThatWontWork)
        .then((response) => { console.log(response); })
        .catch((error) => { console.log(error); });

The browser does 1 HTTP GET (no pre-flight) request that returns an HTTP 500 with the following message in the response

"Request format is unrecognized for URL unexpectedly ending in '/GetInformation'."

But this works:

    const url: string = "http://legacy.mydev.machine:1259/MyService.asmx/GetInformation";
    const optionsThatWillWork: AxiosRequestConfig = {
        withCredentials: true,
        data: {
            // Adding this empty data object makes a difference
        }
    };
    axios.get(url, optionsThatWillWork)
        .then((response) => { console.log(response); })
        .catch((error) => { console.log(error); });

In this case the browser makes 2 requests. The first is an HTTP OPTIONS request that return with a 200 then the second is a GET that successfully hits the GetInformation endpoint and returns a 200 with the json data.

When comparing the 2 HTTP GET messages the only difference that I can see is that the successful one has a Content-Type: application/json;charset=utf-8 header.

I tried adding in that header manually but that didn't work either:

    const optionsThatStillWontWork: AxiosRequestConfig = {
        withCredentials: true,
        headers: {
            "Content-Type": "application/json;charset=utf-8"
        },
    };

I have configured CORS in the legacy site's Owin pipeline using Microsoft.Owin.Cors:

Private Sub ConfigureCors(ByVal app As IAppBuilder)
    Dim corsPolicy = New CorsPolicy() With {
        .AllowAnyMethod = True,
        .AllowAnyHeader = True,
        .SupportsCredentials = True,
        .AllowAnyOrigin = False
    }

    corsPolicy.Origins.Add("http://newsite.mydev.machine:9050")

    Dim corsPolicyProvider = New CorsPolicyProvider With {
        .PolicyResolver = Function(context) Task.FromResult(corsPolicy)
    }

    Dim options = New CorsOptions With {
        .PolicyProvider = corsPolicyProvider
    }

    app.UseCors(options)
End Sub

Note: both http://legacy.mydev.machine:1259 and http://newsite.mydev.machine:1259 have entries in my hosts file pointing to 127.0.0.1.

According to the axios documentation the data config option is

"Only applicable for request methods 'PUT', 'POST', and 'PATCH'"

... which I would agree with.

Couple of questions then:

  1. Why does adding the empty data object make this work?
  2. Why does the first example not do a pre-flight?
  3. Does my CORS setup in the legacy site look ok?
1 Answers

It seems to an issue in server-side code.

  1. Probably it's because of Content-Type added automatically because data is provided. Even for GET request that does not send payload.
  2. Preflight is not sent for "simple" request. GET query without any headers outside of whilelist does not require sending preflight.
  3. root cause is not related to CORS(since it returns 200 OK in "special" flow and since it is not touched at all in "normal" flow)

I think it make sense to check you controller code that handles request. Assume there should be content type explicitly specified.

BTW if CORS preflight failed there would be no 500 Internal Server Error for GET request. OPTIONS preflight would fail and there would be no GET request on next move.

Related