Search code examples
c#corsblazorbasic-authenticationpreflight

Blazor WASM NetworkError when attempting to fetch resource. "CORS Missing Allow Origin"


In this Blazor WASM application I am simply trying to consume a third party API - I open up developer tools and see this message "CORS Missing Allow Origin" when I attempt to retrieve the data. In this case I did add request.Headers.Add("Access-Control-Allow-Origin", "*"); to the request but it is still failing. I have verified this result in different browsers other than FF.

enter image description here

The code for the Index.Razor page is here:

@page "/"
@inject HttpClient Http
<h3>Presentations Scheduled</h3>

<form>
    <fieldset class="form-group">
        <div>
            <button type="button" class="btn btn-dark mr-sm-2 mb-2"
                    @onclick=@(async ()=>  await GetToday())>
                Today
            </button>
        </div>
    </fieldset>

    @if (string.IsNullOrWhiteSpace(errorString) == true)
    {
        <div class="h2">No Data</div>
    }
    else if (string.IsNullOrWhiteSpace(errorString) == false)
    {
        <div class="h2">@errorString</div>
    }
</form>

<div class="h2">@TestReturn</div>




@code
{
    TestModel TestReturn;
    string errorString = null;
    string TestBaseURL;
    HttpRequestMessage request;

    private async Task GetToday()
    {
        var byteArray = Encoding.ASCII.GetBytes("user:pass");
        Http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));

        string todayDate = DateTime.Today.AddDays(0).ToString("yyyyMMdd");
        TestBaseURL = "https://webservices.xcompany.com/";
        UriBuilder TestURI = new UriBuilder(TestBaseURL);
        TestURI.Scheme = "https";
        TestURI.Path = "ws/run/reservations.json";
        TestURI.Query = "resource_query_id=246492";
        var TestQuery = HttpUtility.ParseQueryString(TestURI.Query);
        TestQuery["scope"] = "extended";
        TestQuery["start_dt"] = todayDate;
        TestQuery["end_dt"] = todayDate;
        TestURI.Query = TestQuery.ToString();
        TestBaseURL = TestURI.ToString();
        request = new HttpRequestMessage(HttpMethod.Get, TestBaseURL);
        request.Headers.Add("Access-Control-Allow-Origin", "*");

        try
        {
            using var httpResponse = await Http.SendAsync(request);
            TestReturn = await httpResponse.Content.ReadFromJsonAsync<TestModel>();
        }
        catch (Exception ex)
        {
            errorString = $"There was a problem: {ex.Message}";
        }

    }

}

Solution

  • In this case I did add request.Headers.Add("Access-Control-Allow-Origin", "*");

    You don't add such a header. You actually do nothing in this regards. It is the third party's server that has to add this header, not you.

    CORS is a security feature defined as follow:

    Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate (by using such a header as "Access-Control-Allow-Origin", "*") any other origins (domain, scheme, or port) than its own from which a browser should permit loading of resources.

    It is your browser that does not permit the loading of the resources. As far as I recall, the browser gets the response with the data, but instead of loading it, it tells you that it did not find the header "Access-Control-Allow-Origin", "*" in the response, therefore it refuses to load the resources.

    Solution: Ask the people in the third party API to add you to their white-list web sites that can access resources from their web site. I guess this is not practical in your case.

    Since CORS is a JavaScript security feature and is only applicable when you're making a Fetch API call, you can circumvent this limitation by make a call to your own Web API that should call the third party API, gets the data and pass it back to your WebAssembly Blazor App.