Recently at a client’s site I had to write a new API which calls a downstream web API which was secured with Kerberos authentication, or something, I think. Not sure.
I dug up the code for an existing .NET Framework solution which calls the legacy service. The old code looks like this:
WebRequest myWebRequest = WebRequest.Create(serverUrl);
// Set 'Preauthenticate' property to true. Credentials will be sent with the request.
myWebRequest.PreAuthenticate = true;
myWebRequest.Credentials = new NetworkCredential(user, password);
using (WebResponse myWebResponse = myWebRequest.GetResponse())
using (Stream receiveStream = myWebResponse.GetResponseStream())
{
byte[] data = Helper.ReadFully(receiveStream);
I didn’t know what a WebRequest’s NetworkCredential is – but a bit of Fiddler investigation revealed the following header is being sent:
Authorization: Negotiate TlRMTVNTUAADAAAA...
I wasn’t sure how to call this with .NET 6, and it’s not documented in the HttpClient documentation. Fortunately, I eventually found my way to good ol’ Rick Strahl, who has a solution at https://weblog.west-wind.com/posts/2021/Nov/27/NTLM-Windows-Authentication-Authentication-with-HttpClient
In my solution I’m using typed HttpClients which is different to Rick’s custom HttpClient factory implementation. My working solution looks like this:
builder.Services.AddHttpClient<ILegacyClient, LegacyClient>(
client =>
{
client.DefaultRequestHeaders.UserAgent.ParseAdd("My great Api");
client.BaseAddress = new Uri(builder.Configuration["Clients:Legacy:BaseUri"]);
}).ConfigurePrimaryHttpMessageHandler(() =>
{
var username = builder.Configuration["Clients:Legacy:Username"];
var password = builder.Configuration["Clients:Legacy:Password"];
var credentials = new NetworkCredential(username, password);
return new HttpClientHandler { Credentials = credentials, PreAuthenticate = true };
});
Easy once you know how.