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.