Have you watched the ServerCustomValidationRequested event with an HttpBaseProtocolFilter? The tricky part for me was extracting the public certificate from the Certificate object. To do this, I had to bring the System.Security.Cryptography.X509Certificates nuget package. My code is as follows:
private void DoIt() { using (var filter = new HttpBaseProtocolFilter()) { filter.ServerCustomValidationRequested += FilterOnServerCustomValidationRequested; var httpClient = new Windows.Web.Http.HttpClient(filter); var myString = await httpClient.GetStringAsync(new Uri("https://myserver.com")); // I guess we should be kind and unsubscribe? filter.ServerCustomValidationRequested -= FilterOnServerCustomValidationRequested; } } private void FilterOnServerCustomValidationRequested(HttpBaseProtocolFilter sender, HttpServerCustomValidationRequestedEventArgs args) { if (!IsCertificateValid(args.RequestMessage, args.ServerCertificate, args.ServerCertificateErrors)) { args.Reject(); } } private bool IsCertificateValid(Windows.Web.Http.HttpRequestMessage httpRequestMessage, Certificate cert, IReadOnlyList<ChainValidationResult> sslPolicyErrors) { // disallow self-signed certificates or certificates with errors if (sslPolicyErrors.Count > 0) { return false; } if (RequestRequiresCheck(httpRequestMessage.RequestUri)) { var certificateSubject = cert?.Subject; bool subjectMatches = certificateSubject == CERTIFICATE_COMMON_NAME; var certArray = cert?.GetCertificateBlob().ToArray(); var x509Certificate2 = new X509Certificate2(certArray); var certificatePublicKey = x509Certificate2.GetPublicKey(); var certificatePublicKeyString = Convert.ToBase64String(certificatePublicKey); bool publicKeyMatches = certificatePublicKeyString == CERTIFICATE_PUBLIC_KEY; return subjectMatches && publicKeyMatches; } return true; } private bool RequestRequiresCheck(Uri uri) { return uri.IsAbsoluteUri && uri.AbsoluteUri.StartsWith("https://", StringComparison.CurrentCultureIgnoreCase) && uri.AbsoluteUri.StartsWith(BASE_URL, StringComparison.CurrentCultureIgnoreCase); }
source share