akamsteeg / AtleX.HaveIBeenPwned

A modern, fully async, high performance, .NET client library for the API of HaveIBeenPwned.com
https://www.nuget.org/packages/AtleX.HaveIBeenPwned/
MIT License
5 stars 0 forks source link

Error: The request was aborted: Could not create SSL/TLS secure channel. #39

Closed akamsteeg closed 4 years ago

akamsteeg commented 4 years ago

(Reported by e-mail)

A user reported that using AtleX.HaveIBeenPwned fails on .NET 4.6.1 and 4.7.2. They provided a detailed error message:

Message: 
    System.Net.Http.HttpRequestException : An error occurred while sending the request.
    ---- System.Net.WebException : The request was aborted: Could not create SSL/TLS secure channel.
  Stack Trace: 
    TaskAwaiter.ThrowForNonSuccess(Task task)
    TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    <FinishSendAsyncUnbuffered>d__59.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    TaskAwaiter.ThrowForNonSuccess(Task task)
    TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    ConfiguredTaskAwaiter.GetResult()
    <GetResponseDataAsync>d__26.MoveNext() line 569
    --- End of stack trace from previous location where exception was thrown ---
    TaskAwaiter.ThrowForNonSuccess(Task task)
    TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    ConfiguredTaskAwaiter.GetResult()
    <IsPwnedPasswordInternalAsync>d__22.MoveNext() line 448
    --- End of stack trace from previous location where exception was thrown ---
    TaskAwaiter.ThrowForNonSuccess(Task task)
    TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    ConfiguredTaskAwaiter.GetResult()
    <IsPwnedPasswordAsync>d__17.MoveNext() line 327
    --- End of stack trace from previous location where exception was thrown ---
    TaskAwaiter.ThrowForNonSuccess(Task task)
    TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    TaskAwaiter`1.GetResult()
    <IsPwnedPassword_WithValidKnownInputAndCancellationToken__ReturnsTrue>d__2.MoveNext() line 43
    --- End of stack trace from previous location where exception was thrown ---
    TaskAwaiter.ThrowForNonSuccess(Task task)
    TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    --- End of stack trace from previous location where exception was thrown ---
    TaskAwaiter.ThrowForNonSuccess(Task task)
    TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    --- End of stack trace from previous location where exception was thrown ---
    TaskAwaiter.ThrowForNonSuccess(Task task)
    TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    ----- Inner Stack Trace -----
    HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
    HttpClientHandler.GetResponseCallback(IAsyncResult ar)
akamsteeg commented 4 years ago

This appears to be related to the HaveIBeenPwned.com service switching to TLS1.2 and 1.3 only and dropping TLS1.1. I can reproduce this by running the integration tests against .NET 4.6.1 and .NET 4.7.2.

akamsteeg commented 4 years ago

This is fixable by explictly enabling TLS1.2 support and inject a HttpClient into the HaveIBeenPwnedClient:

var s = new HaveIBeenPwnedClientSettings();

using (var hc = new HttpClient())
using (var hibpClient = new HaveIBeenPwnedClient(s, hc)
{
     ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;

    var isPwned = await hibpClient.IsPwnedPasswordAsync("example");
}

However, we should investigating adding this automatically to make this Just Work™.

akamsteeg commented 4 years ago

Okay, obviously you don't need to inject a HttpClient into the HaveIBeenPwnedClient:

using (var hibpClient = new HaveIBeenPwnedClient()
{
     ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;

    var isPwned = await hibpClient.IsPwnedPasswordAsync("example");
}

This fixes the issue too.

akamsteeg commented 4 years ago

Removed the setting in 860bcb1. We don't want to automagically alter any ServicePointManager settings the calling code already might have set. If the calling code runs into an error, they can set the proper values themselves.