I`m setting up a new WebAPI server (ASP NET), we're using HTTPS and checking for a valid password, which is passed through the message header.
Server side, I can check if every package is delivered through HTTPS, and if it contains the correct header with password information.
My question is: We're using refit on the API client, inserting the password as a header on every package. Can the client pass the header, or a single message unencrypted?
Here`s the code:
Connection and initialization
var httpClient = new HttpClient(new AuthenticatedHttpClientHandler())
{
BaseAddress = new Uri("https://10.103.208.16:45456/")
};
var nsAPI = RestService.For<Interface1>(httpClient);
Method call:
var sugars = await nsAPI.GetMakeUps();
HttpHandler which inserts the password
class AuthenticatedHttpClientHandler : HttpClientHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Headers.Add("pw", "MY_SECRET_PW");
return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
}
}
Am I at risk that the password could be sniffed unencrypted? Can I enforce refit to communicate / send packages only through HTTPS connections?
This is just a copy of my answer to the identical question raised as a Refit issue:
Refit uses the standard .NET HttpClient
(you're using one explicitly in your example), so it is as secure as if you were using HttpClient
directly.
In your example, you're setting the base address to an HTTPS URI and that's all Refit will ever use to initiate requests.
However, if your server redirected to a HTTP URI (which is very unlikely) and the HttpClient
was configured to auto-follow redirects (which may be the default), then it is possible for a follow up request to be redirected to this insecure URL. If that were the case, your handler would be sending the password on an insecure request.
This is a fairly unlikely situation, but there's an easy fix anyway -- just check the scheme of the URL before attaching your password:
class AuthenticatedHttpClientHandler : HttpClientHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if(string.Equals(request.RequestUri.Scheme, "https", StringComparison.OrdinalIgnoreCase))
request.Headers.Add("pw", "MY_SECRET_PW");
return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
}
}
That way if you somehow wind up issuing an HTTP request instead of an HTTPS one, you won't send your password with it.
If you're concerned about whether your password is sniffable in an HTTPS request, it's only really possible if the computer running the client has been compromised and is trusting someone it shouldn't. But if that's the case there are easier ways to get at your password e.g. by decompiling the DLL or reading config files, for example.