I have a WinForms app that calls a WCF service hosted on IIS7. For some reason, computers attached to the client network get a 401 Unauthorized error when trying to connect to the WCF Service through the WinForms app. I have spent quite a bit of time trying to figure this out and this is what I have found out so far.
The WinForms app receives the WCF service data on any other PC not on the client network.
From the client network, I can browse to the WCF service through a web browser just fine.
From the client network, I can browse to a service method and get the "Method not allowed"
error as expected.
Also, it should be noted that the WCF service is using REST instead of SOAP.
Here is the code I use to do all the service calls:
byte[] dataStream = Encoding.UTF8.GetBytes(strParameters);
WebRequest webRequest = WebRequest.Create(strUrl + strFunction);
webRequest.Method = "POST";
webRequest.ContentType = "application/json";
webRequest.ContentLength = dataStream.Length;
Stream newStream = webRequest.GetRequestStream();
newStream.Write(dataStream, 0, dataStream.Length);
newStream.Close();
WebResponse response = webRequest.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader responseReader = new System.IO.StreamReader(responseStream, Encoding.UTF8);
string responseString = responseReader.ReadToEnd();
Does anyone have any clues as to why I would be getting the 401 error only on the Client's network?
My suggestion would be to try the call via fiddler from the clients machine and validate if you can get the expected result via a POST. If this is successful I would look into how you are hosting the service in IIS. I have seen on several occasions where the issue was Anonymous or Basic Authentication was turned off which caused similar issues.
Related
I am wrtting a .net core service which fetches some data by calling a api deployed on a docker server.
string url = serviceURL;
WebRequest request = WebRequest.Create(url);
request.Method = "GET";
request.ContentType = "application/json";
request.ContentLength = 0;
using (WebResponse response = await request.GetResponseAsync())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
//logic to access data;
}
}
I get exception # using (WebResponse response = await request.GetResponseAsync())
System.AggregateException: 'One or more errors occurred. (An attempt was made to access a socket in a way forbidden by its access permissions. An attempt was made to access a socket in a way forbidden by its access permissions.)'
Inner Ex HttpRequestException: An attempt was made to access a socket in a way forbidden by its access permissions.
Inner Ex SocketException: An attempt was made to access a socket in a way forbidden by its access permissions.
The same API on docker server is also been called from a windows based application written in .net framework 4.5 and it works fine there and returns the expected result.
What additional proxy setting is required for .net core application to make a web request?
I'm trying to send a JSON request to a REST service that is HTTPS secured. The client explained that the REST service is using self-signed certificates. He also explained that this is a development service and that I should ignore any certificate warnings. (The service is running on a RaspberryPi in our office)
He forwarded me the following CURL request to demonstrate that it's working:
curl -k -H "Content-Type: application/json" -X POST -d '{"MerchantReference":"[removed]",
"Command":"Debit", "Amount":5500,"DeviceSerialNumber":"[removed]"}' https://[removed]
When I establish a connection with Putty and run this, I get a response so all is good. But when I write an app in C# to do this, I get the following exception:
"The underlying connection was closed: An unexpected error occurred on a send." The inner exception is: "Authentication failed because the remote party has closed the transport stream."
Here is my C# code:
var tempRequest = #"{""MerchantReference"":""[removed]"",""Command"":""Debit"",
""Amount"":5500,""DeviceSerialNumber"":""[removed]""}";
HttpWebRequest webRequest = WebRequest.Create(HttpAddress) as HttpWebRequest;
webRequest.Method = WebRequestMethods.Http.Post;
webRequest.ContentType = "application/json";
byte[] buffer = Encoding.UTF8.GetBytes(tempRequest);
Stream postData = webRequest.GetRequestStream();
postData.Write(buffer, 0, buffer.Length);
postData.Close();
var webResponse = webRequest.GetResponse(); // The exception occurred here
I have added a callback to ServicePointManager.ServerCertificateValidationCallback at the start of the application to just accept any certificate but the execution doesn't even reach that part.
So my question would be how to replicate the CURL result in C#.
Any assistance would be greatly appreciated.
I've found the problem. TLS v1.2 is used and we are using .Net 4.0 which only supports up to TLS V1.0. We'll either upgrade to .Net 4.5 or use a different version of TLS.
We're using the HTTPWebRequest objects to make HTTP requests to our application and we're having a problem when the request requires authentication and there is a transparent proxy (Squid 3.1.10).
string url = "http://www.icode.co.uk/test/auth.php";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Credentials = new NetworkCredential("username", "password");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
MessageBox.Show(reader.ReadToEnd());
reader.Close();
stream.Close();
response.Close();
Our original code used the WebClient class which exhibited the same problem.
The first time this code runs, it displays the result correctly.
When the code runs a second time, it fails on the GetResponse() line with:
System.Net.WebException was unhandled
Message="The server committed a protocol violation. Section=ResponseStatusLine"
Source="System"
StackTrace:
at System.Net.HttpWebRequest.GetResponse()
at Dummy.DummyForm.button1_Click(Object sender, EventArgs e) in H:\Trial\Dummy\DummyForm.cs:line 42
at ...
On Windows 7, restarting the process causes it to recover and work once, but Server 2003 requires a full reboot.
Looking at the network capture, two requests are identical to start with, the initial unauthenticated request is sent and the server replies, but the failing requests sends the 2nd authenticated request in the middle of the initial reply as if it's ignoring the Content-Length header (which is correct). It then receives the rest of the initial reply and fails with the protocol error.
It does seem odd that the client (HTTPWebRequest) doesn't close the connection cleanly though.
When the proxy is not in use (non port 80 or internal traffic) the requests all work as expected. When there is no authentication, it also works as it only makes the single request.
I've already reduced the problem code to the minimum and reproduced it with the MSDN sample, but does anyone know if this is a known issue or a problem in our (.NET or Squid) configuration?
Since it only fails the second time, would
request.KeepAlive = false;
make a difference?
I think NTLM authentication (NetworkCredential) does not work at the same time with transparent proxy feature of SQUID. :-(
http://www.squid-cache.org/mail-archive/squid-users/201110/0025.html
Could you try another authentication scheme?
Try authenticating yourself, with
request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(username + ":" + password));
before the request.GetResponse();
This worked for me. First I tried putting in the whole string myself, which didn't work!
I have written a WinForms app that uploads addresses from a spreadsheet, and geocodes them using an external geocoding service. This all works fine on my local machine, but the time has come for it to be installed on other peoples computers for testing. The app no longer works now though, generating the below error:
System.Net.WebException: The remote server returned an error: (407) Proxy Authentication Required.
Having read a lot and chatted breifly to our network guys, it seems i need to establish the Security Context for the users account and work with this to correct the error.
Has anyone got any pointers about how I should be going about this?
Thanks in advance!
C
It depends on how your uploading the data. If your using a http request (as it looks like you are) it will look something like;
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("https://test.example.com/");
req.Method = "POST";
req.ContentType = "text/xml";
req.Credentials = new NetworkCredential("TESTACCOUNT", "P#ssword");
StreamWriter writer = new StreamWriter(req.GetRequestStream());
writer.Write(input);
writer.Close();
var rsp = req.GetResponse().GetResponseStream();
I'm working on a .NET app that calls 3rd party web services over the internet. The services do not use SOAP, so we manually construct an XML request document, send it to the service via HTTP, and retrieve an XML response.
Our code is a Windows service that is run in the context of a normal Windows domain account, and sits behind a proxy server (Microsoft ISA Server) configured to require NTLM authentication. The account running our service has permission to access the internet through the proxy server.
The code looks like this:
// Create the request object.
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
request.Method = "POST";
// Configure for authenticating proxy server requiring Windows domain credentials.
request.Proxy = New WebProxy(proxyAddress) { UseDefaultCredentials = true };
// Set other required headers.
request.Accept = acceptableMimeType;
request.Headers.Add(HttpRequestHeader.AcceptCharset, acceptableCharset);
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "none");
request.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-gb");
request.Headers.Add(HttpRequestHeader.CacheControl, "no-store");
request.Headers.Add(HttpRequestHeader.ContentEncoding, "none");
request.Headers.Add(HttpRequestHeader.ContentLanguage, "en-gb");
request.ContentType = requestMimeType;
request.ContentLength = requestBytes.Length;
// Make the method call.
using(Stream stream = request.GetRequestStream()) {
stream.Write(requestBytes, 0, requestBytes.Length);
}
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
// Extract the data from the response without relying on the HTTP Content-Length header
// (we cannot trust all providers to set it correctly).
const int bufferSize = 1024 * 64;
List<byte> responseBytes = new List<byte>();
using(Stream stream = new BufferedStream(response.GetResponseStream(), bufferSize)) {
int value;
while((value = stream.ReadByte()) != -1) {
responseBytes.Add((byte) value);
}
}
This works fine if the proxy server is turned off, or the URL has been whitelisted as not requiring authentication, but as soon as authentication is active, it always fails with an HTTP 407 error.
I put the above code in a test harness, and tried every method I could think of for configuring the request.Proxy property, without success.
I then noticed that all the 3rd party web services that we have to call are HTTPS. When I tried accessing them as HTTP instead, the proxy authentication started working. Is there some extra hoop I have to jump through to get proxy authentication and HTTPS to play nicely?
PS: The same problems occur with the open source SmoothWall proxy server, so I can't just write it off as a bug in ISA Server.
PPS: I'm aware that you can configure proxy settings in app.config, but (a) doing it in code shouldn't make any difference, and (b) the application design requires that we read the proxy settings from a database at runtime.
Have you tried setting the proxy in the app.config ?
To disable the proxy, in the App.config file add the following configuration
<system.net>
<defaultProxy enabled="false" useDefaultCredentials="false">
<proxy/>
<bypasslist/>
<module/>
</defaultProxy>
</system.net>
To enable the proxy and to use the default proxy settings(specified in IE) add this configuration in your App.config
<system.net>
<defaultProxy enabled="true" useDefaultCredentials="true">
<proxy/>
<bypasslist/>
<module/>
</defaultProxy>
</system.net>
I did have a similar situation
Did you noticed it worked when you accessed the internet before you ran the code? and if you had not accessed the internet for ages (20mins for me) you got the error.
have you tried to set the proxy credentials directly?
//setup the proxy
request.Proxy = new WebProxy("proxyIp", 8080);
request.Proxy.Credentials = CredentialCache.DefaultCredentials;
I hope this fixes your issue too
I think I will have to write off this question. My original posted code does appear to work sometimes. Our proxy server is extremely unreliable; one minute it will block an internet connection from any software, and the next it will allow it. The IT guys seem powerless to do anything about it, and we (everyone outside the IT department) have no authority to make changes to the network infrastructure.
If anyone has any ideas on how to "harden" my code to compensate for an unreliable proxy server, then I'd be interested to hear them. :-)
Is there something wrong with your proxy server's certificate? If your service can't establish HTTPS then it will throw an error.