Durante l’esecuzione di una chiamata ad una webapi, può capitare che il certificato SSL non riesca a superare le verifiche, impedendo la possibilità di accedere alla risorsa. Ovviamente, per poter poter risolvere il problema è buona norma occuparsi della generazione di un certificato valido lato server ed eventualmente importare la CA sul client, ma può capitare di non poterlo fare.
Utilizzando il client HttpClient di c# l’errore che viene ritornato è simile al seguente:
[xx:xx:xx ERR] Connection ID "XXXXXXXXXXXXXXXXXXXXXXX", Request ID "XXXXXXXXXXXXXXXXXXXXX": An unhandled exception was thrown by the application. System.AggregateException: One or more errors occurred. (The SSL connection could not be established, see inner exception.) ---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
Il messaggio indicata in maniera piuttosto esplicita che non è possibile effettuare la chiamata per un problema sul certificato. La validazione del certificato può fallire per diversi motivi, ad esempio l’utilizzo di un self-signed, la presenza di un certificato scaduto o peggio ancora revocato. O più semplicemente stiamo effettuando uno sviluppo interno.
Il framework .NET (nel mio caso si tratta della versione 4.8) ci mette a disposizione una particolare funzionalità che consente di disabilitare la verifica.
La classe che deve essere utilizzata è la ServicePointManager:
ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => { return true; };Questa chiamata “forza” sostanzialmente il runtime a credere che il processo di convalida del certificato sia andato a buon fine. A questo punto è necessario modificare leggermente il codice per effettuare le chiamate HTTP:
E’ stato creato un nuovo httpClientHandler che è stato passato come parametro all’interno del costruttore di HttpClient.
var EndPoint = "ENDPOINTURL";
var httpClientHandler = new HttpClientHandler();
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) =>
{
return true;
};
httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(EndPoint) };Da questo punto in avanti sarà possibile effettuare le chiamate HTTP come se la validazione SSL sia stata effettuata correttamente.
Lo svantaggio evidente è che si tratta di una forzatura, quindi tutte le chiamate effettuate in questo modo non saranno coinvolte dalla validazione del certificato.