What is the proper way to use basic authentication? - c#

I am pretty much new to RestSharp and am bit confused about the below two code blocks (numbered).
var client = new RestClient("url"); // client
client.Authenticator = new HttpBasicAuthenticator("username", "password");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", string.Format("Basic {0}", "username:password"));
IRestResponse response = client.Execute(request);
when to use authentication in client section and when to use it in request section. If we add basic authenticator in client object itself then is it required to bind it in every request that we make?
It would be helpful if someone can explain or direct me to right contents.

when to use authentication in client section
When you use one client to issue multiple requests that all need the same authorization.
and when to use it in request section.
When you want to issue a single request that requires authorization.
If we add basic authenticator in client object itself then is it required to bind it in every request that we make?
No.
See also Authenticators on RestSharp's GitHub Wiki.

Related

Restsharp parameter behavior when setting ParameterType=GetOrPost

I face a weird intermittent issue with RestSharp. I use it to submit a POST authentication request to a server. But under certain conditions that I cannot isolate yet, this authentication call fails. By looking at the server log, I see a GET request instead of a POST. And I really wonder how the hell it is possible.
Here is the code to submit the authentication request :
var client = new RestClient(m_baseUrl);
var request = new RestRequest("https://dummyserver.com/api/auth", Method.POST);
request.AddParameter("client_id", apiCredentials.ApiKey, ParameterType.GetOrPost);
request.AddParameter("client_secret", apiCredentials.ApiSecret, ParameterType.GetOrPost);
request.AddHeader("Content-Type", "multipart/form-data");
IRestResponse response = await client.ExecutePostTaskAsync(request);
Since it is a distributed application, I don't have much info on the client request. Telemetry just confirms that the authentication failed.
Is it possible (known bug) that RestSharp transformed this request into a GET?
And, second question, is there any difference on the request being created with those two syntaxes:
request.AddParameter("client_id", apiCredentials.ApiKey, ParameterType.GetOrPost);
request.AddParameter("client_id", apiCredentials.ApiKey);
I need parameters to be submitted as form-data for security purposes.
Thanks for your help.
I don't think it's possible that a POST request gets executed as GET. Consider that you have some code (not the code from your question), which does that. Even using ExecutePost is redundant when you explicitly set the request type in the RestRequest constructor.
Concerning the second question, there's no real difference. The default parameter type is GetOrPost. I also believe that we use multipart/form-data for POST requests by default where there's no JSON or XML body.
You can easily find it by looking at the code of RestSharp.
Although weird, I've experienced a similar issue with you.
My solution is to use ExecuteAsPost():
var response = client.ExecuteAsPost(request, "POST");

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.

Authorization bearer token with NEST elasticsearch and C#

I've got a problem while trying to connect to an elasticsearch API.
The API expect an bearer token, but the NEST lybrary only provides a basic authentication and I've got to pass a custom header as well. So, did anybody have to face this problem?? How to pass custom headers?!
Thanks
You can add headers that should be added to all requests on ConnectionSettings
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connectionSettings = new ConnectionSettings(pool)
.GlobalHeaders(new NameValueCollection
{
{ "Authorization", "Bearer fnoi3nfion3fn00jr0j1r0" }
});
var client = new ElasticClient(connectionSettings);
Actually I was getting a mistaken concept. Actually I'm interacting with an API wich encapsolate the elasticsearch and just use the elasticsearch query sintax, so I didn't need to use NEST, the elasticsear package, to connect with it. And I just got to interact it with a simple http call.
Anyway, thanks Russ
you can add any header to your request:
req.Headers.Add("CustomeKey", CustomeData);

web api Bad Request when getting access token after moving to production

I have a web api that is working great in test using an access token / bearer authentication. I authenticate and make requests using HttpClient. Easy.
Here is the basic web client setup. The base address is a constant that I change when moving to production.
public static HttpClient GetClient()
{
HttpClient Client = new HttpClient();
Client.BaseAddress = new Uri(Ics2Constants.ICS2APIBaseAddress);
Client.DefaultRequestHeaders.Accept.Clear();
Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
return Client;
}
I build the token request login info like so:
var values = new Dictionary<string, string>();
values.Add("grant_type", "password");
values.Add("username", "niceUser");
values.Add("password", "NiCePaSsWord");
var loginContent = new FormUrlEncodedContent(values);
And then I make the request for the access token:
var loginResponse = await client.PostAsync("/Token", loginContent);
In test mode, perfect. I can get my access token, pass it back on subsequent requests. All is good.
When I move to production. I get a bad request 400 on the request for access token. I do have the base address right because if I take off the authorize attribute I can get data back.
Something is different about the request for access token in production, but I have no clue what to change.
Well, the answer ended up being two part:
1) Issue with the web host. They had a corruption on their end.
2) After they fixed their issue I still received a 404 (not found)... so I had to take out the "/" in my PostAsync. So the new line looks like so:
var loginResponse = await client.PostAsync("Token", loginContent);
It worked in debug on the local side with the "/", but the production side was not happy.
I'm up and working now. :)

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