Reputation: 1310
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
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