Manish Joisar
Manish Joisar

Reputation: 1310

How to disable preflight request to MarkLogic server from C# WebApi

Tech stack as follows

We have developed MarkLogic API with basic authentication and while calling it from C# WebApi, we are passing credentials in header.

We noticed that MarkLogic access logs is having 2 entries i.e.

Same request goes with 401 i.e. Unauthorized and then immediately with 200 i.e. successful.

We realized that calling API endpoint from C# WebAPI is a doing preflight request with OPTIONS before calling actual request.

We found there is option to send content type as 'text/plain' to solve this issue, but we can't as we have JSON object and then we need to do more to parse text to JSON object.

When we are calling from PostMan, we are facing with the same problem.

Due to this, when we have loads of requests on API, ML API returns with 401 error on Firewall and then FW blocks all requests considering it as Brute Force Attack.

Is there any way, we can disable preflight request calling?

MarkLogicHttpClient _client;

var queryParams = new Dictionary<string, string>
{
    { "query", searchRequest.Query },
    { "offset", searchRequest.Offset.ToString() },
    { "size", searchRequest.Size.ToString() },
    { "format", searchRequest.Format },
    { "sortOrder", searchRequest.SortOrder.ToString().ToUpper() },
    { "transform", transform }
};

var searchUri = QueryHelpers.AddQueryString("getcontent", queryParams);

var response = await _client.GetAsync(searchUri);

//Startup.cs

services.AddHttpClient<IMarkLogicClient, MarkLogicHttpClient>(client =>
{
    client.BaseAddress = MarkLogicEndpoint;
})
.ConfigurePrimaryHttpMessageHandler(() =>
    new HttpClientHandler
    {
        Credentials = new NetworkCredential
        {
            UserName = UserName,
            Password = Password
        }
    }
);

Upvotes: 1

Views: 236

Answers (1)

Brent Ellingson
Brent Ellingson

Reputation: 356

The HttpClient sends an Authorization header only after first receiving a 401 response with a WWW-Authenticate header from the server.

By default, HttpClient waits for the 401 response before authorizing on every request.

There are two ways to reduce the number of 401 responses.

Set the HttpClientHandler.PreAuthenticate Property

services.AddHttpClient<IMarkLogicClient, MarkLogicHttpClient>(client =>
{
    client.BaseAddress = MarkLogicEndpoint;
})
.ConfigurePrimaryHttpMessageHandler(() =>
    new HttpClientHandler
    {
        // cache the WWW-Authenticate response and send Authorize header
        // on all subsequent requests
        PreAuthenticate = true,
        Credentials = new NetworkCredential
        {
            UserName = UserName,
            Password = Password
        }
    });

Or, manually add Authorize Header to HttpClient.DefaultRequestHeaders

services.AddHttpClient<IMarkLogicClient, MarkLogicHttpClient>(client =>
{
    // construct HTTP Basic Authorization header and send on every request
    // Do not add credentials to HttpClientHandler
    var authorization= "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(Username + ":" + Password));
    client.BaseAddress = MarkLogicEndpoint;
    client.DefaultRequestHeaders.Add("Authorization", authorization);
});

Upvotes: 1

Related Questions