How do I pass credentials with DalSoft.RestClient? - c#

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

Related

HttpClient send Auth header

I'm using HttpClient to call some REST API with authentication like this:
_networkCredential = new NetworkCredential(username, apiKey);
_httpClientHandler = new HttpClientHandler { Credentials = _networkCredential };
_httpClient = new HttpClient(_httpClientHandler);
This works nicely, but as defined in RFC2617 this will send every request without AUTH header, gets back a 401 and then sends the request a second time with AUTH header.
I'd like to get rid of the extra call without AUTH header to achieve better throughput. For BASIC AUTH I found the following example to manually add the BASIC AUTH header to every call:
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{apiKey}")));
But my service insists on DIGEST AUTH. How can I achieve this in DIGEST AUTH?
I'd guess I'd have to call the service once and cache the AUTH HEADER for subsequent calls. But if the nonce changes I'd need to refresh the AUTH HEADER? How could this be solved?

How to conveniently extract single response cookies from a shared static HttpClient without mixing cookies from other parallel requests?

I'm working on a web application that needs to proxy some requests to some other internal website.
I'm using a shared static HTTP client instance to avoid performance issues, according to these articles:
https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
https://medium.com/#nuno.caneco/c-httpclient-should-not-be-disposed-or-should-it-45d2a8f568bc
Obviously, I don't want to blindly store cookies coming back from HttpClient and then blindly send them back because that would mess up cookies coming from different web requests to my website. So, I have turned cookie usage off:
var httpClientHandler = new HttpClientHandler
{
// make sure we don't share cookies
// when sending requests over our shared HttpClient instance
UseCookies = false,
// if API returns a redirect, we want to let the caller handle it
AllowAutoRedirect = false,
AutomaticDecompression = DecompressionMethods.GZip
};
var apiClient = new HttpClient(httpClientHandler);
However, there are situations when I need to extract and process cookies from a specific HttpClient web request in my web app.
I can see the required cookies present in HttpResponseMessage headers:
var setCookieHdr = response.Headers.GetValues("set-cookie");
The problem - setCookieHdr is a string and not a convenient CookieCollection.
Is there any simple and thread-safe way to turn the "set-cookie" header into a CookieCollection?
I have seen examples using
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
HttpClient client = new HttpClient(handler);
HttpResponseMessage response = client.GetAsync("http://google.com").Result;
Uri uri = new Uri("http://google.com");
IEnumerable<Cookie> responseCookies = cookies.GetCookies(uri).
but I highly suspect that such approach would lead to race conditions. The handler could have stored the last cookie value coming from a parallel proxy-ed HttpClient response and not the response my proxy controller method is currently working on, because HttpClient is a shared static instance, together with the handler and its CookieContainer.
I need to extract cookies just from this specific response and not mess with any current cookies of the shared static HttpClient - those cookies should be ignored completely to avoid mixing them for multiple parallel requests.

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);

AuthenticationHeaderValue Vs NetworkCredential

I'm trying to write a client for either HTTP Post or HTTP Get using HttpClient. When Googling around I come across these methods that set these authentication within the HttpClient object. One uses NetworkCredential while the other uses AuthenticationHeaderValue
HttpClient sClient;
HttpClientHandler sHandler = new HttpClientHandler();
sHandler.Credentials = new NetworkCredential("UserName", "Password");
sClient = new HttpClient(sHandler);
OR
HttpClient sClient new HttpClient();
sClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Basic",Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes("UserName:Password")));
Reading on MSDN does not give me a distinct answer about the differences between them. Is this a case where both will do the same thing except how its authentication information is stored? such as AuthenticationHeaderValue puts it in the header while the other doesn't? Is one better than the other in term of my use case or best practices ?
The 2nd approach is more flexible in such way that you can specify a type of authentication (e.g., anonymous, basic, window, certificate, etc) to use.
If your first approach doesn't work, try to specify the 3rd param on NetworkCredential, which is the domain name.

Restful, Proxy and webapi

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.

Categories