I've got two servers (X and Y) that are trying to communicate, but failing to do so over TLS1.2 (TLS1.1, and TLS1.0 both behave correctly).
I've got a server X that is failing to get a response from localhost
.
The call that is throwing an exception is this line of code
HttpResponseMessage response = await httpClient.GetAsync(address, cancel);
where address is https://localhost/XXXXX/Identity/.well-known/jwks
and cancel is IsCancellationRequested = false
I noticed that the server certificate being presented for https://localhost/XXXXX/Identity/.well-known/jwks
is one that is valid, signed with RSA256, not on a revocation list, etc etc, everything looks good, but the subject is *.testing.corp, which doesn't match the URL I am trying to navigate to. This causes a certificate warning when navigating to https://localhost/XXXXX/Identity/.well-known/jwks
from Chrome on server X, but after manually clicking through it I get the results I expect.
So my thought is that if I can override the cert validation of HttpClient.GetAsync, I should be able to make this work, so I add the following code around my client:
var handler = new WebRequestHandler();
httpClient = new HttpClient(handler);
handler.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(dumbvalidationdeletemeishouldnotbeversioned);
public static bool dumbvalidationdeletemeishouldnotbeversioned(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors err)
{
return true;
}
The interesting bit is that this never hits, when I step to the GetAsync
line of code, a step throws the exception without ever hitting the dummy validation.
What is going on? Why else could this method fail?
Even more context:
EDIT: Related, X is utilizing Identity Server to attempt to authenticate. The failure is occuring when trying to access https://localhost/XXXXX/Identity/.well-known/jwks
I am using IISCrypto to configure the protocols on these machines. (Taking @Oleg's advice in the comments did not change this behavior). I have configured them by clicking the "Best Practices" button and then un-checking TLS1.0 and TLS1.1, so that both servers look like this:
EDIT: Adding some stack trace information
Before I added my dummy handler, this is the thrown exception's stack trace:
System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
--- End of inner exception stack trace ---
at System.Net.TlsStream.EndWrite(IAsyncResult asyncResult)
at System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
--- End of inner exception stack trace ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at XXXXXXXX.Authentication.Extensions.XXXXXXOpenIDConnectAuthentication.<ReadJWTKeys>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at XXXXXXX.Authentication.Extensions.XXXXXXOpenIDConnectAuthentication.<MessageRecieved>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Owin.Security.OpenIdConnect.OpenIdConnectAuthenticationHandler.<AuthenticateCoreAsync>d__1a.MoveNext()
After adding the dummy handler, the exception is completely null <-- see the comments. The exception is exactly the same, but the return statement in my dummy handler is never hit when I debug the process, so the crux of my question changes to "What else is there to check?"
One should add
(from
System.Net
namespace) before call ofto force the usage of correct protocol. See the blog with detailed experiments with
HttpClient
andServicePointManager.SecurityProtocol
.