title: SSL Error "The message received was unexpected or badly formatted" for a .NET application on one specific machine only
body: <p>I have a .NET Core 3.1 C# application which is calling an API via HTTPS (and presenting its public key as part of getting the token as that certificate is later used to decrypt information sent back separately). On just about all our machines, it is working, but on one Windows 8.1 machine, we get the following series of exceptions when we try to initially connect for an authentication token:</p>
  <pre><code>The SSL connection could not be established, see inner exception.
  ---&gt; System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
  ---&gt; System.ComponentModel.Win32Exception (0x80090326): The message received was unexpected or badly formatted.
  </code></pre>
  <p>The exception is thrown from <code>System.Net.Http.HttpClient.FinishSendAsyncBuffered</code> so I suspect it is happening at the HTTPS level and our certificate stuff is not really relevant here anyway.</p>
  <p><strong>Our code to get the token looks like this:</strong></p>
  <p>The constructor for the auth service:</p>
  <pre><code>  public XXXXAuthService(IXXDbService dbService, XXXXApiConfig config)
          {
              _dbService = dbService;
              _config = config;
              
              // try forcing TLS1.2 for SSL connection exceptions thrown in some operating environments
              ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
              
              _httpClient = new HttpClient {BaseAddress = new Uri(config.BaseUrl)};
              _httpClient.DefaultRequestHeaders.Accept.Clear();
              _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(&quot;application/json&quot;));
          }
  </code></pre>
  <p>Code to get the auth token:</p>
  <pre><code>private async Task&lt;string&gt; GetXXXXBearerToken(string userId, DateTime creationTime)
          {
              var token = await GenerateProviderJwtForXXXX(userId, creationTime);
              var kvp = new List&lt;KeyValuePair&lt;string, string&gt;&gt;
              {
                  new KeyValuePair&lt;string, string&gt;(&quot;grant_type&quot;, &quot;urn:ietf:params:oauth:grant-type:token-exchange&quot;),
                  new KeyValuePair&lt;string, string&gt;(&quot;subject_token&quot;, token),
                  new KeyValuePair&lt;string, string&gt;(&quot;subject_token_type&quot;, &quot;urn:ietf:params:oauth:token-type:jwt&quot;)
              };
              var data = new FormUrlEncodedContent(kvp);
              var publicKey = await GetXXXXPublicKey();
  
              _httpClient.DefaultRequestHeaders.Remove(&quot;X-XXXX-Public-Cert&quot;);
              _httpClient.DefaultRequestHeaders.Add(&quot;X-XXXX-Public-Cert&quot;, publicKey);
  
              var response = await _httpClient.PostAsync(&quot;Identity/token&quot;, data);
              if (!response.IsSuccessStatusCode)
                  throw new Exception(&quot;XXXX Token Server Error: &quot; + response.ReasonPhrase);
              var result = await response.Content.ReadAsStringAsync();
  
              var authResponse = JsonConvert.DeserializeObject&lt;OAuthResponse&gt;(result);
  
              if (!string.IsNullOrEmpty(authResponse.access_token))
                  return authResponse.access_token;
  
              System.Diagnostics.Trace.WriteLine(&quot;Token Exchange Result: &quot; + result);
              if (!string.IsNullOrEmpty(authResponse.error))
              {
                  var outcome = new XXX.XXXX.Model.OperationOutcome();
                  outcome.Issue.Add(new XXX.XXXX.Model.OperationOutcome.IssueComponent()
                  {
                      //some code to throw an error is here
              }
  
              throw new XXX.XXXX.Rest.XXXXOperationException(&quot;Bearer Token Exchange failed&quot;, response.StatusCode);
          }
  </code></pre>
  <p>Unfortunately none of the existing questions/advice anywhere on Stack Overflow, or the rest of the web, for this particular error seems to have helped. They are primarily about version discrepancies between client and server which seems not to be the case here as I am forcing TLS 1.2 (which is active and enabled on the failing machine).</p>
  <p>Interestingly, I can visit the server URL in a browser via HTTPS just fine, which suggests there is something about my code that is the problem rather than the machine, but it works everywhere else.</p>
  <p>I have confirmed that:</p>
  <ul>
  <li>The certificate I am using to authenticate the connection on the machine is valid and has a chain of trust (though as above I don't think we are getting that far as the TLS connection itself is failing)</li>
  <li>The server we are calling supports TLS 1.2 (by forcing it)</li>
  <li>I can get to the website for the URL independently via the browser</li>
  </ul>
  <p>Is there something I need to do either in the code or on the machine to get this call to work everywhere?</p>
  <p><strong>Things I have tried to resolve the issue</strong></p>
  <ul>
  <li>Installing all Windows 8.1 updates to present day</li>
  <li>Forcing TLS 1.2 in the code (see above code sample)</li>
  <li>Limiting VM to TLS 1.2 only</li>
  </ul>