Wordpress api not allowing rejecting server-side connection - asp.net

I'm trying to connect to our wordpress api in our asp.net mvc application, using the following code
public static string GetLifespeakBlogListings()
{
WebClient client = new WebClient();
string url = "https://lifespeak.com/wp-json/wp/v2/posts?categories=6";
string listings = client.DownloadString(url);
return listings;
}
however I'm getting the following exception :
System.Security.SecurityException Failed to negotiate HTTPS connection with server.fiddler.network.https> HTTPS handshake to lifespeak.com (for #1) failed. System.IO.IOException Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
If I access this feed from a browser, it works fine https://lifespeak.com/wp-json/wp/v2/posts?categories=6
However, if I try from fiddler, I get the same exception:
I'm assuming that something on our wordpress site is blocking this request for some reason. Is there something I can configure to prevent this? How can I determine the cause?

The issue was that the version of System.Net I was using in my application was attempting to make the request to the wordpress API using TLS 1.0, and was getting rejected, similar to the issue with fiddler that dave pointed out above. I fixed this by adding the following line of code in the method, as specified in How to specify SSL protocol to use for WebClient class
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
Note that the value has to be added manually and cast as a SecurityProtocolType, as .net 4.0 (the version I was using) doesn't support tls1.2

Related

XmlReader.Create error "Could not create SSL/TLS secure channel"

On my ASP.net-based website I am aggregating feeds of my activities from several website.
One of those is the GitHub feed at https://github.com/lucamauri.atom: this is a valid feed correctly readable using a web browser and it properly worked on my website since a couple of weeks ago. Since then, it started generating errors
In the code I first create and XMLReader and then I load it in a SyndicationFeed object as follows:
Dim TempReader As System.Xml.XmlReader = System.Xml.XmlReader.Create(TempString)
Dim SyndFeed As SyndicationFeed = SyndicationFeed.Load(TempReader)
Dim TempItems As New List(Of SyndicationItem)
TempItems.AddRange(SyndFeed.Items.ToList.GetRange(0, Math.Min(CurrentFeed.TotalElements, SyndFeed.Items.Count)))
This works properly with several feeds, but the GitHub one now generate a TLS error on the first row of the above code:
System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
at System.Net.HttpWebRequest.GetResponse() at System.Xml.XmlDownloadManager.GetNonFileStream(Uri uri, ICredentials credentials, IWebProxy proxy, RequestCachePolicy cachePolicy)
at System.Xml.XmlDownloadManager.GetStream(Uri uri, ICredentials credentials, IWebProxy proxy, RequestCachePolicy cachePolicy)
at System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn)
at System.Xml.XmlTextReaderImpl.FinishInitUriString() at System.Xml.XmlTextReaderImpl..ctor(String uriStr, XmlReaderSettings settings, XmlParserContext context, XmlResolver uriResolver)
at System.Xml.XmlReaderSettings.CreateReader(String inputUri, XmlParserContext inputContext)
at System.Xml.XmlReader.Create(String inputUri, XmlReaderSettings settings, XmlParserContext inputContext)
at System.Xml.XmlReader.Create(String inputUri)
I use the same code with other HTTPS feeds (https://stackoverflow.com/feeds/user/69295 just to name one) and I do not get the error. So this is something specific to the GitHub feed, but then again I can reach it from a browser on the same machine where I run the website, so I am lost at it.
Any idea on the cause of the issue?
The server is in control of the protocol that is ultimately negotiated. The Stackoverflow server is requiring only TLS v1 as shown in the wireshark capture below. This trace was done on .Net framework version 4.
The Github feed refuses anything below TLS v1.2 and therefore fails on .Net 4.0 because that version is not available by default.
You can work around it by setting the SecurityProtocol on the ServicePointManager, if you have .Net 4.5+ installed on the same computer. If you don't, then you simply cannot make the request.
You do this by using the numeric value for the SecurityProtocol instead of the enumeration value which is not available on .Net 4.
ServicePointManager.SecurityProtocol = DirectCast(3072, SecurityProtocolType)
Having done this, you can now negotiate TLS 1.2 even on .Net 4.
However, if you can, just upgrade to a newer framework version to make it easy.
Update
There is a patch available for .Net 3.5:
https://support.microsoft.com/en-us/help/3154520/support-for-tls-system-default-versions-included-in-the-net-framework
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
.NET 4.5.1
Set this in startup class of mvc project and xmlreader worked on https links, thanks guys.

HttpClient.GetAsync works with LocalHost API, but not Live API

I have a .Net 4.5.2 WebApp that is calling my API. When I point my web app to the LocalHost version of my API, it gets the data, and comes back just fine. I published that API, and confirm that the API is working correctly with PostMan.
Then I run the exact same WebApp code, changing only the URI from localhost to live api, and I get a multiple exception error consisting of the following:
An existing connection was forcibly closed by the remote host
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
The underlying connection was closed: An unexpected error occurred on a send.
An error occurred while sending the request.
Here's my calling code
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("user", serializedUser);
response = null;
try
{
//Uri uri = new Uri("https://jsonplaceholder.typicode.com/posts/1");//https works
Uri uri = new Uri("https://api.acme.com/values/test");
//Uri uri = new Uri("http://localhost/5000/values/test"); //http localhost works
response = client.GetAsync(uri).Result;
}
catch (Exception e)
{
string er = e.Message;
}
}
EDIT 1: I created a .NET Core app from scratch, and my original code works perfectly calling my live API. My original code also work in .NET 4.5.2 calling a different "https" API.
EDIT 2:
So this is where I'm at now, I have created two generic apps from VS 2015, one is a .NET Core Web App, the other a .NET Framework Web App. I have used the above code exactly the same in both apps to call the API. In both apps, I can call a generic "https" api I found online (jsonplaceholder). I can also call the localhost version of my app at "http" from both. In the .NET Core version of the app, I can call my "https" live API and get the results I'm looking for. In the .NET Framework app I still get the same errors.
I can't figure out what the difference is between my Core and Framework requests that is getting one shut down when the other isn't.
It seems you are hosting the application on secured http environment (https). Are you using SSL certificate on the server where you are hosting your Web API? If not, It might be throwing the certificate related exceptions.
Just add the following line before the call to GetAsync and This will ignore the SSL errors.
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
This is only recommended in an intranet environment or other closed network where server identities can't be forged.
C# Ignore certificate errors?
Adding the following line before my API call fixed the issue, but I'd love to hear an explanation of what this line does, and any security risks this might impose using it in my web app.
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
Props to this answer!

Visual Studio 2013 WebTest Request Failed: An existing connection was forcibly closed by the remote host

I'm attempting to run a Visual Studio 2013 web test on my local machine. This is a test that I've run successfully (the last time about 2 months ago). The first step in the web test is a GET request to a login page. It looks like this:
GET https://example.com/Login.aspx
When I type this url into a web browser it succeeds. Also, I can successfully record a web test where I merely navigate to this page and log in. But when I attempt to re-run the webtest that I just recorded I get this response to the GET request:
Request failed: An existing connection was forcibly closed by the remote host
Nothing is logged by IIS on example.com (IIS does not log the GET request). But, when I manually log in, or when I record the web test, IIS does log the GET request properly.
There are no messages logged in the event viewer on example.com or on my local host.
Any suggestions on how to debug this issue are much appreciated.
For me, the problem was a TLS handshake. Solved by adding a plug-in to web test.
Think is original question, that helps me: https://social.msdn.microsoft.com/Forums/vstudio/en-US/bc3ebf23-575d-4e54-bd6b-a1ed87fe5213/web-performance-test-is-not-working-with-tls12-enabled?forum=vstest
Plugin source:
using System;
using System.ComponentModel;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using Microsoft.VisualStudio.TestTools.WebTesting;
[Description("This plugin will force the underlying System.Net ServicePointManager to negotiate downlevel SSLv3 instead of TLS. WARNING: The servers X509 Certificate will be ignored as part of this process, so verify that you are testing the correct system.")]
public class TLSPlugin : WebTestPlugin
{
[Description("Enable or Disable the plugin functionality")]
[DefaultValue(true)]
public bool Enabled { get; set; }
public override void PreWebTest(object sender, PreWebTestEventArgs e)
{
base.PreWebTest(sender, e);
//For TLS
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
//For SSL
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
//we wire up the callback so we can override behavior and force it to accept the cert
ServicePointManager.ServerCertificateValidationCallback = RemoteCertificateValidationCB;
//let them know we made changes to the service point manager
e.WebTest.AddCommentToResult(this.ToString() + " has made the following modification-> ServicePointManager.SecurityProtocol set to use SSLv3 in WebTest Plugin.");
}
public static bool RemoteCertificateValidationCB(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
//If it is really important, validate the certificate issuer here.
//this will accept any certificate
return true;
}
}
Today I faced a similar problem with Visual Studio 2017 Enterprise and after a couple of hours, able to resolve it.
I added below two registry keys in my machine where Visual Studio is installed and it resolved the issue.
For a complete description of setting, Refer documentation:-
https://support.microsoft.com/en-in/help/4040243/how-to-enable-tls-1-2-for-configuration-manager
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
Two entries of SchUseStrongCrypto key needs to be done in the registry just like below snapshot.
Visual Studio 2019 - Load Test
Scenario: Using unit test for the load test.
Problem: When running the unit test manually it runs without problems. As soon as the load test starts it fails with same error: "An existing connection was forcibly closed by the remote host".
Solution: Force TLS1.2 when initializing the unit test.
[TestInitialize]
public void Init()
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
}

Windows 8.1 application does not do the NTLM Negotiation required by Windows Authentication

I have a Windows 8.1 Store application that I side-load on a Windows 10 Enterprise DELL tablet. The app uses data from a repository via an ASP.NET Web API installed on a remote server. The Web API is configured to use Windows Authentication. If I use Fiddler to make Web API calls I can see the several steps in the NTLM negotiation, the 401.2 HTTP Error messages returned twice before the HTTP 200 Ok.
However, my application gets the 401.1 and then it does not do anything else. In my application's package manifest, I have checked Enterprise Authentication check box in the list of required capabilities. Also, when I tested it with the Visual Studio Simulator, on my development machine, the negotiation was done and the Web API responded properly to my calls.
In order to have the NTLM Negotiation done automatically in the background, I though all that needs to be done is to have an HttpClientHandler object constructed like this:
var webApiAuthClientHandler = new HttpClientHandler()
{
Credentials = CredentialCache.DefaultNetworkCredentials,
ClientCertificateOptions = ClientCertificateOption.Automatic
};
Then, this HttpClientHandler object would be passed in the constructor of the HttpClient object used to make the Web API calls:
var webApiHttpClient = new HttpClient(webApiAuthClientHandler)
{
BaseAddress = new Uri(_myWebApiUri, UriKind.Absolute),
Timeout = new TimeSpan(0, 0, 150)
};
What am I missing? How do I get my app to automatically negotiate the authentication in the background and have my GetAsync call return the needed HTTP Code 200?
Any suggestion would be highly appreciated.
TIA,
Eddie
I see your issue has been resolved in MSDN forum: https://social.msdn.microsoft.com/Forums/windowsapps/en-US/58620579-240d-49da-8538-cee5aff91a68/w81-sideloaded-windows-81-application-generates-an-exception-when-calling-methods-of-an-restful?forum=wpdevelop
So I post it here to help more visitors find the solution easily.
Thank you.

Unable to use WebService specifing the URI through code

I have two PCs conected with a LAN. Firewall ports are opened.
I'm running a WebService on A machine, using IIS. Of course, I can access the WebService (on A) through the Web Browser on the B machine, so I'm sure the WebService can be accessed remotely.
Now, I'm running a console app on B machine, developed in vb.net, which will access the WebService of A machine.
Both, the console app and the WebService, has been developed on VS2010.
Creating the reference on the project, I can see and use the WebService. But I need to specify on code the URI due to the WebService may change its location.
The code indicating the URI manually:
Dim myService As New MiServicioWeb.WebServiceSoapClient("192.168.1.13:8080")
This line throw an exception with the message that did not find any element with the name indicated. I have tried too, without success, the following lines:
This one:
Dim myService As New MiServicioWeb.WebServiceSoapClient("192.168.1.13")
And this one:
Dim myService As New MiServicioWeb.WebServiceSoapClient("192.168.1.13:8080/ServicioWeb.asmx")
But the result is always the same.
Some user (raja) wrote an answer a few days ago indicating that this should work, but I don't know the reason why does not work in my case.
As I said before, if I create the reference on the project, and I use the following line of code:
Dim myService As New MiServicioWeb.WebServiceSoapClient()
It works!, but what I need is to set the URI manually...
Some help will be thankful.
if not already present, you need to modify the proxy class to have a constructor that can take a Uri and set it. This Uri needs to be supplied to the proxy.
Dim uriFromConfig as String;
// read uriFromConfig from config or set it accordingly.
Dim myService As New MiServicioWeb.ServicioWebSoapClient(uriFromConfig);
this way, any ASMX can be called, as long as the right Uri is provided.
in summary to call a webservice hosted on machine with IP a.b.c.d from another machine:
Give the Proxy Uri with the IP Address. a.b.c.d
Open the port (50594) you're using in the machine hosting the web service from the Firewall settings.
Verify if the asmx is accesible by typing http://a.b.c.d:50594/ServicioWeb.asmx from the browser of the client machine. (not the machine hosting the web service)
if #3 is successful, then you'll see a nice page on the browser.
your client app should also be able to connect now.

Resources