I'm getting an error when using RestSharp DigestAuthenticator - asp.net-core

So I have a .net core API that's trying to use RestSharp(which I'm fairly new to) to call another API. This other API apparently requires Digest based authentication to access, so I went ahead and tried using the DigestAuthenticator class provided by RestSharp. However, the result was an error saying Header not found : Digest Realm. Image of error below.
RestSharp DigestAuthenticator Error
So, I'm assuming that I would need to add a header for digest auth in my request. But, how would I go about doing that?
Below is what I've done so far,
RestClient client = new RestClient();
RestRequest request = new RestRequest();
client.BaseUrl = new System.Uri("http://ip_address:port/otherApi");
client.Authenticator = new DigestAuthenticator("myusername", "mypassword");
request.Method = Method.POST;
//not sure how to add header for digest auth
//request.AddHeader("")
request.AddParameter("application/xml", xmlString, ParameterType.RequestBody);
client.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
IRestResponse response = client.Execute(request);
return Ok(response.Content);

Related

C# HttpClient failing to make GET requests with Windows Authentication

I have a .NET Core 3.1 Api application with the following configuration of HttpClient. In Startup.cs
services.AddAuthentication(IISDefaults.AuthenticationScheme);
services.AddHttpClient("myapi", c =>
{
c.BaseAddress = new Uri(Configuration["endpoint"]);
c.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(
IISDefaults.AuthenticationScheme, Convert.ToBase64String(
System.Text.Encoding.UTF8.GetBytes($"{Configuration["username"]}:{Configuration["password"]}")));
});
I then try to make an HTTP call like this:
var client = clientFactory.CreateClient(clientName);
HttpResponseMessage response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
return await response.Content.ReadAsStringAsync();
however I always get an Unauthorized response when calling an internal api. Under Debug I have Windows authentication and Anonymous authentication both enabled.
With Postman my api calls go through, which verifies that I got the right credentials.
Can you suggest any alterations to make this work?
Instead of c.DefaultRequestHeaders.Authorization =, I'm having config like this
c.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
Credentials = new NetworkCredential("username", "password"),
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
PreAuthenticate = true
});
I guess this will not work as-is in your case, but I hope this can get you on track.

Using httpClient.postasync for web api calls .netcore

I am new to .netcore, I am working on web api that are running on docker container and while using postman the web api's are working really fine outputting the results. I want to make a program in .netcore calling the webapi endpoints and getting the response and using that particular response in other endpoints with MVC.
The explanation is given below.
The default username and password for admin is default set for example username:admin , password: helloworld
. The first time admin login the api requires a new personal password as shown in the Postman figure below.
The login api is: localhost://..../v1/users/login
The first question is How to give the values in Authorization->BasicAuth using .netcore.
The body of the api looks like the figure below.
After setting the new_password the response of the api is a token as given below.
The particular token is then use in the Environment to create user. The image for more clear problem is given below.
Lastly, the token then used to make other API calls such as creating a user.
API: https://localhost/..../v1/users
The image is below.
As a newbie in .netcore language, I am really struggling to do this kind of API calls, as most of the tutorials I tried are generating their own token from API, but here I just want to take the response token and save it and then use it in other API calls.
The StackOverflow community's support was always really handy for me.
The Code I'm trying is given below.
**Controller**
public class Login_AdminController : ControllerBase
{
[Route("/loginAdmin")]
[HttpPost]
public async Task<string> LoginAdminAsync([FromBody] dynamic content)
{
LoginAdmin L = new LoginAdmin();
var client = new HttpClient();
client.BaseAddress = new Uri("https://localhost:9090");
var request = new HttpRequestMessage(HttpMethod.Post, "/v1/users/login");
var byteArray = new UTF8Encoding().GetBytes($"<{L.username}:{L.df_Password}>");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
var formData = new List<KeyValuePair<string, string>>();
formData.Add(new KeyValuePair<string, string>("new_password", "helloWorld123!"));
request.Content = new FormUrlEncodedContent(formData);
var response = await client.SendAsync(request);
Console.WriteLine(response);
return content;
}
}
}
***Model***
public class LoginAdmin
{
public string username = "admin";
public string df_Password = "secret";
public string new_Password { get; set; }
}
Thank you.
Do you want to get token from response? If yes. Try this:
var client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:12345/Api");
var request = new HttpRequestMessage(HttpMethod.Post, "/token");
var keyValues = new List<KeyValuePair<string, string>>();
keyValues.Add(new KeyValuePair<string, string>("username", "yourusername"));
keyValues.Add(new KeyValuePair<string, string>("password", "yourpassword"));
request.Content = new FormUrlEncodedContent(keyValues);
var response = client.SendAsync(request).Result;
return response.Content.ReadAsStringAsync().Result;
Authorization is handled via the Authorization request header, which will include a token of some sort, prefixed by the scheme. What you're talking about here isn't really basic auth. With that, you literally pass the username and pass in the Authorization header with each request. What you're doing is just authenticating once to get an auth token, and then using that auth token to authorize further requests. In that scenario, you should really be posting the username and pass in the request body. Then, you'd do bearer auth with the token for the other requests, using the Authorization header. Still, to cover both bases:
Basic Auth
var token = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{username}:{password}"));
request.Headers.Add("Authorization", $"Basic {token}");
Bearer Auth
request.Headers.Add("Authorization", $"Bearer {token}");
// where `token` is what was returned from your auth endpoint
FWIW, List<KeyValuePair<string, string>> is just Dictionary<string, string>. It's better to use the real type. Then, you can just do formData.Add("new_password", "helloWorld123!") instead of formData.Add(new KeyValuePair<string, string>("new_password", "helloWorld123!"))

NTLM Auth with RestSharp

I am attempting to create some tests using RestSharp for a project I am working on.
This project uses Single Sign-on NTLM Authentication.
I am attemping to use a NTLMAuthenticator but my getUser request is always failing. I am not positive what URL to put in for the CredentialCache, the project or the SSO Id Provider.
SharedRequests shared = new SharedRequests();
var credential = new CredentialCache
{
{
new Uri("project or ID Provider URL or something else?"),
"NTLM",
new NetworkCredential("doamin\Username", "Password")
}
};
RestClient client = new RestClient();
client.BaseUrl=new Uri("projectURL");
client.Authenticator = new NtlmAuthenticator(credential);
client.PreAuthenticate = true;
RestRequest request = shared.GetCurrentUser();
IRestResponse response = client.Execute(request);
my response always gets a 500 error which is what is expected when no auth cookies are present.

Survey Monkey is Giving me an Invalid Authorization in Request Header Error

I am using the .NET HttpClient in xamarin forms to try to connect to survey monkey. I am new to HttpClient, Xamarin, REST, and survey monkey so I could be making mistakes anywhere or everywhere.
I've had some success using the survey monkey examples with curl and I am trying to convert that to C# code with HttpClient.
I have some "test code" like
HttpClient httpClient = new HttpClient();
Uri uri = new Uri("https://api.surveymonkey.net/v2/surveys/get_survey_list?api_key=humkanu389g5dp9tvsdrh8fv");
HttpContent content = new StringContent(String.Empty,Encoding.UTF8,"application/json");
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization","Bearer XXXXXXXXX");
httpClient.Timeout = TimeSpan.FromSeconds(10);
HttpResponseMessage response = Task.Run(() => httpClient.PostAsync(uri,content)).Result;
String responseContent = Task.Run(() => response.Content.ReadAsStringAsync()).Result;
In my code, I have replaced the XXXXXXX's with my authorization token.
But I am getting a response like
{"status":1,"errmsg":"Invalid \"Authorization\" data in request header"}
I am wondering if I am handling the AuthenticationHeaderValue() part wrong. Or something else?
Your header is not in the correct format, you have "Authorization bearer XXXXX" as the value. So it looks like this:
Authorization: Authorization bearer XXXXX
I'm not sure why based on your code, you should debug and see the value you are sending out. But it should be:
Authorization: bearer XXXXX
My assumption is AuthenticationHeaderValue is doing something you're not expecting. Searching the docs it looks like you're doing it right - so I'm not sure exactly what's wrong with the C# code, just that the header you're sending out is not correct.
General Kandalaft really pointed out the problem--which in retrospect was obvious, but I want to post the final code here in case someone else is trying this.
I ended up fixing the AuthenticationHeaderValue as pointed out above. Then I ran into a problem because my request content was an empty string. I put in some json text from an example and it worked. So the final code
HttpClient httpClient = new HttpClient();
Uri uri = new Uri("https://api.surveymonkey.net/v2/surveys/get_survey_list?api_key=humkanu389g5dp9tvsdrh8fv");
HttpContent content = new StringContent ("{ \"fields\": [ \"title\", \"date_modified\" ] }",Encoding.UTF8,"application/json");
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer","XXXXXX");
httpClient.Timeout = TimeSpan.FromSeconds(10);
HttpResponseMessage response = Task.Run(() => httpClient.PostAsync(uri,content)).Result;
String responseContent = Task.Run(() => response.Content.ReadAsStringAsync()).Result;

OAuth 2.0 authentication in RestSharp

I am trying to authenticate RESTful service (sabre REST api) using RESTsharp library but i am not able to authenticate it. I am using my Client id and secret. Please tell me how to authenticate using oAuth 2.0 authenticator.
I have tried this code. ( sabre is using OAuth 2.0 authentication )
public ActionResult Index()
{
var client = new RestClient("https://api.test.sabre.com");
client.Authenticator = new HttpBasicAuthenticator("myclientid", "myclientsecret");
RestRequest request = new RestRequest("/v1/auth/token", Method.POST);
request.AddHeader("Authorization", "Basic " + client);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("grant_type", "client_credentials");
IRestResponse response = client.Execute(request);
var content = response.Content;
ViewBag.R = content;
return View();
}
i got this result
{"error":"invalid_client","error_description":"Credentials are missing or the syntax is not correct"}
please tell what i am doing wrong.
Thanks
Snapshot of Fiddler Comparison of Running code (not with RestSharp) and code using RestSharp is shown
With RestSharp
Seems to me like you are adding the Authorization header twice. The documentation here says
The authenticator’s Authenticate method is the very first thing called
upon calling RestClient.Execute
Looking at the implementation of HttpBasicAuthenticator, the Authenticate method adds the appropriate header to the request.
So remove the following line from your example:
request.AddHeader("Authorization", "Basic " + client);
You need to first obtain access token from Sabre that you can later use while making rest api calls.
The access token POST request looks like this:
POST https://api.test.sabre.com/v2/auth/token
Authorization: Basic ZVc5MWNtTnNhV1Z1ZEdsazplVzkxY21Oc2FXVnVkSE5sWTNKbGRBPT0=
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
where the value of Authorization after Basic is the Base64 encoded string based on your clientId and secret
Refer to Sabre Authentication on how this string is created
So, in order to get the access token you just need to send a POST request with required header and request parameters and you do not need to use the Authenticator