Restful, Proxy and webapi - c#

I'm developing a consumer app for a publically avalible rest webservice.
I'm having 2 problems: My proxy and the service authentication.
i cant seem to get past my proxy, actually i do have a valid credential to get by it, but i dont know where or how to provide it!
And second, i also dont know how to responde the basic authentication challenge issued by the web-service...
I do can use it via browser, but i cant get it working on my c# app. Heres the code so far:
HttpClient cli = new HttpClient();
cli.BaseAddress = new Uri("http://myserver.com/");
HttpResponseMessage response = cli.GetAsync("api/service1").Result;
textBox1.Text = response.Content.ReadAsStringAsync().Result;
the result in textBox1 so far is always a 407 error... Can anyone help?
Edit1: Authentication on the webservice is of the type BASIC!
Edit2: clientHandler.Credentials = new NetworkCredential("user", "P#ssw0rd"); does not work... server returns "This request requires HTTP authentication"

Proxy information needs to be configured on the HttpClientHandler object which can be passed into the HttpClient constructor.
var clientHandler = new HttpClientHandler();
clientHandler.Proxy = new WebProxy("http://proxyserver:80/",true);
var httpClient = new HttpClient(clientHandler);
For credentials I do something like this...
var clientHandler = new HttpClientHandler() {PreAuthenticate = true};
var credentialCache = new CredentialCache();
credentialCache.Add(new Uri(Host), "Basic", new NetworkCredential(userName, password));
clientHandler.Credentials = credentialCache;
By setting this up this way, whenever you make a request to any URI that is below the "Host" URI, HttpClientHandler will automatically set the correct authorization header.
Also, be aware there is an alternative handler called WebRequestHandler that can be used instead of HttpClientHandler that add in extra stuff that is only available on the Windows OS like WinINet proxy and Pipelining.

Related

CredentialCache and HttpWebRequest in .NET

I'm having difficulty understanding how web requests and credentials work in .NET.
I have the following method that is executing a request to a SOAP endpoint.
public WebResponse Execute(NetworkCredential Credentials)
{
HttpWebRequest webRequest = CreateWebRequest(_url, actionUrl);
webRequest.AllowAutoRedirect = true;
webRequest.PreAuthenticate = true;
webRequest.Credentials = Credentials;
// Add headers and content into the requestStream
asyncResult.AsyncWaitHandle.WaitOne();
return webRequest.EndGetResponse(asyncResult);
}
It works well enough. However, users of my applications may have to execute dozens of these requests in short succession. Hundreds over the course of the day. My goal is to implement some of the recommendations I've read about, namely using an HttpClient that exists for the entire lifetime of the application, and to use the CredentialCache to store user's credentials, instead of passing them in to each request.
So I'm starting with the CredentialCache.
Following the example linked above, I instantiated a CredentialCache and added my network credentials to it. Note that this is the exact same NetworkCredential object that I was passing to the request earlier.
NetworkCredential credential = new NetworkCredential();
credential.UserName = Name;
credential.Password = PW;
Program.CredCache.Add(new Uri("https://blah.com/"), "Basic", credential);
Then, when I go to send my HTTP request, I get the credentials from the cache, instead of providing the credentials object directly.
public WebResponse Execute(NetworkCredential Credentials)
{
HttpWebRequest webRequest = CreateWebRequest(_url, actionUrl);
webRequest.AllowAutoRedirect = true;
webRequest.PreAuthenticate = true;
webRequest.Credentials = Program.CredCache;
// more stuff down here
}
The request now fails with a 401 error.
I am failing to understand this on several levels. For starters, I can't seem to figure out whether or not the CredentialCache has indeed passed the proper credentials to the HTTP request.
I suspect part of the problem might be that I'm trying to use "Basic" authentication. I tried "Digest" as well just as a shot in the dark (which also failed), but I'm sure there must be a way to see what kind of authentication the server is expecting.
I have been combing StackOverflow and MDN trying to read up as much as possible about this, but I am having a difficult time separating the relevant information from the outdated and irrelevant information.
If anyone can help me solve the problem that would be most appreciated, but even links to proper educational resources would be helpful.
According to the documentation the CredentialCache class is only for SMTP, it explicitly says that it is not for HTTP or FTP requests:
https://msdn.microsoft.com/en-us/library/system.net.credentialcache(v=vs.110).aspx
Which directly contradicts the info in the later api docs. Which one is right I don't know.
You could try using the HttpClient class. The methods and return types are different, so you would need to tweak your other a code a bit, but it would look a bit like this:
public class CommsClass
{
private HttpClient _httpClient;
public CommsClass(NetworkCredential credentials)
{
var handler = new HttpClientHandler { Credentials = credentials };
_httpclient = new HttpClient(handler);
}
public HttpResponseMessage Execute(HttpRequestMessage message)
{
var response = _httpClient.SendAsync(message).Result;
return response;
}
}
You can do all sorts of other things with the handler, and the client like set request headers or set a base address.

Default proxy in .net core 2.0

I saw couple of questions asked about core 2.0 on how to make HttpClient to use default proxy configured on the system. But no where found right answer. Posting this question hoping someone who might have encountered this issue might have found the solution by now.
In .net framework versions I've used the following configuration in my web.config and it worked for me.
<system.net>
<defaultProxy useDefaultCredentials="true"></defaultProxy>
</system.net>
But in .net core 2.0 where I've make a web request to external api from my company's intranet my code is failing with 407, proxy authentication required.
After little bit of research I am of the opinion that it is not possible to make your HttpClient to use default proxy settings configured via WPAD in IE. Can someone correct my understanding here?
On this page of https://github.com/dotnet/corefx/issues/7037
It is said as follows :
"The default for HttpClientHandler.UseProxy property is true. And the default value of HttpClientHandler.Proxy is NULL which means to use the default proxy."
But I don't observe this behavior.
Update:
I am finally able to call external web api by specifying the proxy server address and then making the HttpClient call. Still wondering how to use default proxy setup in IE.
using (var handler = new HttpClientHandler {
Credentials = new System.Net.NetworkCredential(user, password, domain),
UseProxy = true,
Proxy = new System.Net.WebProxy(new Uri("http://xxxxxxx:8080"), true)
})
{
handler.Proxy.Credentials = new NetworkCredential("xxxx", "yyyyy", "cccccc");
using (var httpClient = new HttpClient(handler))
{
var request = new HttpRequestMessage()
{
RequestUri = new Uri(destinationUrl),
Method = HttpMethod.Post
};
request.Content = new StringContent(requestXml, Encoding.UTF8, "text/xml");
HttpResponseMessage response = await httpClient.SendAsync(request);
Task<Stream> streamTask = response.Content.ReadAsStreamAsync();
}
}
If any one interested in finding out how I was able to find out the proxy server was, I wrote the following code in .net 4.0 and found out the proxy used.
var proxy = WebRequest.GetSystemWebProxy();
var url = proxy.GetProxy(new Uri("http://google.com"));
Thanks
I hope this is the answer you're looking for: Default Proxy issues #28780
If you simply want to use the default system proxy and need to pass default credentials to that proxy (because the proxy is an authenticated proxy) during HTTP requests, then do this:
var handler = new HttpClientHandler();
handler.DefaultProxyCredentials = CredentialCache.DefaultCredentials;
var client = new HttpClient(handler);

How do I pass credentials with DalSoft.RestClient?

I am attempting to use DalSoft.RestClient to make restful calls to an internal service which requires network credentials (for my use case a default credential) be provided.
The constructor for RestClient provides an overload to pass in an IHttpClientWrapper which I could implement handling credentials, but am hoping there's an out of the box solution for passing credentials to RestClient.
How do I pass credentials to the DalSoft.RestClient?
For any credentials that are set via a header such as basic or oauth you can use the Headers methods. Example for oauth2 bearer token:
dynamic client = new RestClient("http://localhost/");
client
.Headers(new { Authorization = "Bearer " + bearerToken })
.MyResource
.Get();
If you are talking about kerberos or ntlm at the moment there is no method to do this but as you suggested you can implement IHttpClientWrapper to do this. Strangely Credentials are passed to a HttpClient using a HttpClientHandler. Below is an example of how to do this:
HttpClientHandler handler = new HttpClientHandler();
handler.Credentials = new NetworkCredential();
HttpClient client = new HttpClient(handler);
I realize implementing IHttpClientWrapper just to do this isn't ideal, so if you need this functionality I'll look at adding it to the ctor. It would look like this:
HttpClientHandler handler = new HttpClientHandler();
handler.Credentials = new NetworkCredential();
new RestClient("http://localhost/", new Config(handler));
Update this is now supported as of 3.0

Proxy with HTTP Requests

Would it be possible to route a GET request through a proxy by specifying the host as the proxy? Or would you have to set the destination of the packet?
I am trying to generate an HTTPRequestMessage and route it through a proxy. However, I do not have fine level control of setting the destination of the request being sent out.
I was able to add a proxy to HttpClient, HttpWebRequest and HttpRequestMessage. They do not have to be used together, but I just found two ways of making HTTP Requests with proxy. To do this in windows store/metro applications, you would have to implement IWebProxy.
Take a look at this for implementing IWebProxy: http://social.msdn.microsoft.com/Forums/windowsapps/en-US/6e20c2c0-105c-4d66-8535-3ddb9a048b69/bug-missing-type-webproxy-cant-set-proxy-then-where-is-the-appconfig
Then all you need to do is set the proxy for HttpClient or HttpWebRequest:
HttpClient:
HttpClientHandler aHandler = new HttpClientHandler();
IWebProxy proxy = new MyProxy(new Uri("http://xx.xx.xx.xxx:xxxx"));
proxy.Credentials = new NetworkCredential("xxxx", "xxxx");
aHandler.Proxy = proxy;
HttpClient client = new HttpClient(aHandler);
HttpWebRequest:
HttpWebRequest webrequest = (HttpWebRequest)WebRequest.CreateHttp(uri);
IWebProxy proxy = new MyProxy(new Uri("http://xx.xx.xx.xxx:xxxx"));
proxy.Credentials = new NetworkCredential("xxxx", "xxxx");
webrequest.Proxy = proxy;
HttpRequestMessage
Once you construct an HttpRequestMessage, you can use the method above (HttpClient) to send this request message and it will be routed through the proxy without any additional work.

C# Windows Store App HTTPClient with Basic Authentication leads to 401 "Unauthorized"

I am trying to send a HTTP GET request to a service secured with BASIC authentication and https. If I use the RESTClient Firefox plugin to do so there is no problem. I am defining the basic-header and sending the GET to the url and I am getting the answer (data in json).
Now I am working on a Windows Store App in C# which is meant to consume the service. I enabled all required capabilities in the manifest and wrote the following method:
private async void HttpRequest()
{
string basic = "Basic ...........";
Uri testuri = new Uri(#"https://...Servlet");
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", basic);
Task<HttpResponseMessage> response = client.GetAsync(testuri);
var text = await response;
var message = text.RequestMessage;
}
I tried out many different possibilites like getting the response-string but everything lead to an 401 Status Code answer from the Server.
I looked at many similar problems and my understanding of the communication is the following: Client request -> Server response with 401 -> Client sends Authorization header -> Server response with 200 (OK)
What I don't understand is why I am getting the 401 "Unauthorized" Status Code although I am sending the Authorization header right at the beginning. It would be interesting if someone knows how this is handled in the RESTClient.
The BASIC header is definetly correct I was comparing it with the one in the RESTClient.
It would be great if someone could help me with this.
Thanks in advance and kind regards,
Max
Was having a similar problem, i added a HttpClientHandler to HttpClient.
var httpClientHandler = new HttpClientHandler();
httpClientHandler.Credentials = new System.Net.NetworkCredential("","")
var httpClient = new HttpClient(httpClientHandler);
Credentials should be encoded, before adding to the header. I tested it in WPF app, It works...
string _auth = string.Format("{0}:{1}", "username", "password");
string _enc = Convert.ToBase64String(Encoding.UTF8.GetBytes(_auth));
string _basic = string.Format("{0} {1}", "Basic", _enc);
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization",_basic);

Categories