I wrote an API call in a WCF web service that passes a JSON string via POST. When i did the call over the webservice, i get an error, but when i did the call over a simple little testapp, i did not get an error. Here are some details and the abbreviated code.
WCF target Framework: .NET Framework 4.8.1 Running in IIS under his own Application Pool and his own service user.
Server: Windows Server 2019, .NET Framework 4.8
TestApp: WinForms (.NET Framework), targetFrameWork 4.8, startet under my Windows user
//on class
private static readonly UTF8Encoding _utf8 = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
//on method
HttpWebRequest webRequest = WebRequest.CreateHttp(uri);
webRequest.Method = "POST";
webRequest.ContentType = "application/json";
webRequest.Headers.Add("Cache-Control", "no-cache");
webRequest.PreAuthenticate = true;
string _certificateThumbprint = "XXX";
bool _validCertificateOnly = true;
X509Store store = new X509Store(StoreLocation.LocalMachine);
//store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
store.Open(OpenFlags.ReadWrite | OpenFlags.OpenExistingOnly);
X509Certificate2Collection certCollection = store.Certificates;
X509Certificate2 certificate = certCollection.Find(X509FindType.FindByThumbprint, _certificateThumbprint, validOnly: _validCertificateOnly).OfType<X509Certificate2>().FirstOrDefault();
if (certificate != null && (!_validCertificateOnly || certificate.Verify()))
{
webRequest.ClientCertificates.Add(certificate);
}
string _authUsername = "YYY";
string _authPassword = "ZZZ";
string creds = Convert.ToBase64String(_utf8.GetBytes(_authUsername + ":" + _authPassword));
webRequest.Headers["Authorization"] = $"Basic {creds}";
string jsonString = "Some JSON data...";
byte[] Content = _utf8.GetBytes(jsonString);
webRequest.ContentLength = Content.Length;
//Error
using (Stream RequestStream = webRequest.GetRequestStream())
{
RequestStream.Write(Content, 0, Content.Length);
}
I don't understand why it doesn't work via the web service but works via the test app. Here a little info from the web.config:
<system.web>
<compilation debug="true" targetFramework="4.6" />
<httpRuntime targetFramework="4.5.2" />
</system.web>
When use web.config like this, i get:
System.IO.IOException: Authentication failed because the remote party has closed the transport stream.
When use web.config with 4.8 on both, i get:
System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
When I called the API from the web service, the other party told me that the certificate had not been sent. When i call the API from the TestApp, it works just fine.
If some more info needed, please let me know, i will try to provide it.
I wrote an API call in a WCF web service that passes a JSON string via POST. When i did the call over the webservice, i get an error, but when i did the call over a simple little testapp, i did not get an error. Here are some details and the abbreviated code.
WCF target Framework: .NET Framework 4.8.1 Running in IIS under his own Application Pool and his own service user.
Server: Windows Server 2019, .NET Framework 4.8
TestApp: WinForms (.NET Framework), targetFrameWork 4.8, startet under my Windows user
//on class
private static readonly UTF8Encoding _utf8 = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
//on method
HttpWebRequest webRequest = WebRequest.CreateHttp(uri);
webRequest.Method = "POST";
webRequest.ContentType = "application/json";
webRequest.Headers.Add("Cache-Control", "no-cache");
webRequest.PreAuthenticate = true;
string _certificateThumbprint = "XXX";
bool _validCertificateOnly = true;
X509Store store = new X509Store(StoreLocation.LocalMachine);
//store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
store.Open(OpenFlags.ReadWrite | OpenFlags.OpenExistingOnly);
X509Certificate2Collection certCollection = store.Certificates;
X509Certificate2 certificate = certCollection.Find(X509FindType.FindByThumbprint, _certificateThumbprint, validOnly: _validCertificateOnly).OfType<X509Certificate2>().FirstOrDefault();
if (certificate != null && (!_validCertificateOnly || certificate.Verify()))
{
webRequest.ClientCertificates.Add(certificate);
}
string _authUsername = "YYY";
string _authPassword = "ZZZ";
string creds = Convert.ToBase64String(_utf8.GetBytes(_authUsername + ":" + _authPassword));
webRequest.Headers["Authorization"] = $"Basic {creds}";
string jsonString = "Some JSON data...";
byte[] Content = _utf8.GetBytes(jsonString);
webRequest.ContentLength = Content.Length;
//Error
using (Stream RequestStream = webRequest.GetRequestStream())
{
RequestStream.Write(Content, 0, Content.Length);
}
I don't understand why it doesn't work via the web service but works via the test app. Here a little info from the web.config:
<system.web>
<compilation debug="true" targetFramework="4.6" />
<httpRuntime targetFramework="4.5.2" />
</system.web>
When use web.config like this, i get:
System.IO.IOException: Authentication failed because the remote party has closed the transport stream.
When use web.config with 4.8 on both, i get:
System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
When I called the API from the web service, the other party told me that the certificate had not been sent. When i call the API from the TestApp, it works just fine.
If some more info needed, please let me know, i will try to provide it.
Share Improve this question edited Mar 17 at 15:45 Lex Li 63.5k11 gold badges124 silver badges161 bronze badges asked Mar 17 at 8:04 BummzuaBuaBummzuaBua 434 bronze badges 3 |1 Answer
Reset to default -1So i get down to the problem.
I installed Fiddler to see what happened.
My first Problem is, i get from Fiddler a different error as i get from .NET Framework.
Fiddler told me, that the Problem is the verfication of the Server certificate from the server i called.
To verify this, I added the following line of code and tested whether it works:
ServicePointManager.ServerCertificateValidationCallback += (o, c, ch, er) => true;
That worked. That means the problem is that we don't trust the authority's root certificate, or rather, the certificate isn't present in the trusted Root store.
When installing the cert into the root, the problem is solved.
Thanks for the answers.
Edit: For somebody who maybe have the same Problem - Do not use this in prod enviroment.
Just for testcase, but delete it afterwards!
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;
– Jalpa Panchal Commented Mar 19 at 8:44