最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - API call with certificate over webservice isn't working - Stack Overflow

programmeradmin3浏览0评论

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
  • An HTTPS (secure) uses TLS to encrypt the connection. TLS is performed before the HTTP request is sent. Error message indicates the TLS failed. A certificate contains an encryption mode. Either the certificate is not loaded on both client and server or the encryption mode is not supported in the Net Version (en.wikipedia./wiki/Transport_Layer_Security). The latest Windows OS only supports TLS 1.2 and TLS 1.3. The wrong version of TLS may be issue. Starting with Net 4.7.1 TLS is performed in OS while older version of Net TLS is done in Net. There are lots of reason TLS fails. – jdweng Commented Mar 17 at 10:00
  • Please show your wcf web.config Also, if you use wcf, where is your service client? – AllanC Commented Mar 17 at 19:29
  • could you try setting the tls version directly in your code like this: ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls | SecurityProtocolType.Ssl3; – Jalpa Panchal Commented Mar 19 at 8:44
Add a comment  | 

1 Answer 1

Reset to default -1

So 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!

发布评论

评论列表(0)

  1. 暂无评论