У меня есть приложение. NET Core 3.1 C#, которое вызывает API через HTTPS (и представляет свой publi c ключ как часть получения токена, поскольку этот сертификат позже используется для расшифровки информации, отправленной обратно отдельно ). Практически на всех наших машинах он работает, но на одном компьютере Windows 8.1 мы получаем следующую серию исключений, когда пытаемся первоначально подключиться для токена аутентификации:
The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
---> System.ComponentModel.Win32Exception (0x80090326): The message received was unexpected or badly formatted.
Исключение составляет выброшено из System.Net.Http.HttpClient.FinishSendAsyncBuffered
, поэтому я подозреваю, что это происходит на уровне HTTPS, и наш сертификат здесь в любом случае не имеет отношения.
Наш код для получения токена выглядит так:
Конструктор для службы аутентификации:
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("application/json"));
}
Код для получения токена аутентификации:
private async Task<string> GetXXXXBearerToken(string userId, DateTime creationTime)
{
var token = await GenerateProviderJwtForXXXX(userId, creationTime);
var kvp = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "urn:ietf:params:oauth:grant-type:token-exchange"),
new KeyValuePair<string, string>("subject_token", token),
new KeyValuePair<string, string>("subject_token_type", "urn:ietf:params:oauth:token-type:jwt")
};
var data = new FormUrlEncodedContent(kvp);
var publicKey = await GetXXXXPublicKey();
_httpClient.DefaultRequestHeaders.Remove("X-XXXX-Public-Cert");
_httpClient.DefaultRequestHeaders.Add("X-XXXX-Public-Cert", publicKey);
var response = await _httpClient.PostAsync("Identity/token", data);
if (!response.IsSuccessStatusCode)
throw new Exception("XXXX Token Server Error: " + response.ReasonPhrase);
var result = await response.Content.ReadAsStringAsync();
var authResponse = JsonConvert.DeserializeObject<OAuthResponse>(result);
if (!string.IsNullOrEmpty(authResponse.access_token))
return authResponse.access_token;
System.Diagnostics.Trace.WriteLine("Token Exchange Result: " + 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("Bearer Token Exchange failed", response.StatusCode);
}
К сожалению, ни один из существующих вопросов / советов нигде в Stack Overflow или остальная часть Интернета, похоже, помогла именно эта ошибка. В основном они связаны с расхождениями в версиях между клиентом и сервером, что, похоже, здесь не так, поскольку я принудительно использую TLS 1.2 (который активен и включен на отказавшей машине).
Интересно, что я могу посетить URL-адрес сервера в браузере через HTTPS нормально, что говорит о том, что проблема в моем коде, а не в машине, но она работает везде.
Я подтвердил, что:
- Сертификат, который я использую для аутентификации соединения на машине, действителен и имеет цепочку доверия (хотя, как и выше, я не думаю, что мы зашли так далеко, поскольку само соединение TLS не работает)
- вызываемый нами сервер поддерживает TLS 1.2 (принудительно)
- Я могу перейти на веб-сайт по URL-адресу независимо через браузер
Есть ли что-то, что мне нужно сделать в код или на машине, чтобы этот вызов работал везде?
Что я пытался решить проблему
- Установка всех обновлений Windows 8.1 до сегодняшнего дня
- Принудительное использование TLS 1.2 в коде (см. Пример кода выше)
- Ограничение виртуальной машины только TLS 1.2