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

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;

Related

I'm getting an error when using RestSharp DigestAuthenticator

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

NetCore 3.1 PostAsync CustomHeaders not working

I have several RESTful services that working with each other. In one scenario I want to post some data from one service to another service and I want to attach some information in Header of the request. I saw several cases to do this and in the end I came up with this workaround:
var httpClient = new HttpClient();
httpClient.Timeout = TimeSpan.FromMinutes(3);
var httpRequestMessage = new HttpRequestMessage {
Method = HttpMethod.Post,
RequestUri = new Uri(service2Address),
Content = new StringContent(JsonConvert.SerializeObject(obj))
};
httpRequestMessage.Headers.Add("myCustomHeaderKey", "myCustomHeaderValue");
var response = await httpClient.SendAsync(httpRequestMessage);
var responseString = await response.Content.ReadAsStringAsync();
With these lines of code, a Post request sent, but in service2 when I want to get the headers from request, there is no sign of myCustomHeaderKey in headers collection. I inspect Request.Headers in Visual Studio Watch and even try to get custom header with Request.Headers["myCustomHeaderKey"]. So what's wrong here?
EDIT 1
This implementation in based on this tutorial.
I have developed code like yours. Have created Two Asp.net core 3.1 project with standart template. One service is starting localhost:44320 and other localhost:44300
localhost:44320/PostService wrote the your codes.
Then get this url with browser. localhost:44320/weatherforecast/IncomeService function is like below
Finally i put breakpoint to where get request header. Result is like below
There is a not a problem. Maybe you use change request header middleware. Or if you are using something like nginx. this problem maybe nginx configuration.

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!"))

Api calling in .net core razor pages

I am working on (built-in web apis) provided by whatsapp business api. As a newbie in .net core razor pages and web apis. I want to know how can I get access to the body of the post request api. Take an example below for sending a message
Post: {URL}/v1/messages
Request Body:
"to": "",
"message_type:"
"message_text:"
"recipient_type: "individual | group""
How can I make a call to the builtin api and access the body parts of it?
Ofcourse, we as a developer can use postman for checking the working of api. But take this as a client and for the client we have some fields like
To:
Message:
How can take these fields and put it into the api call body and then when the user click on the send, the api call works and shows whatever we want to show the user for example a model with send successfully etc.
You can call the API using HttpClient.
Add the URL in await client.PostAsync() function. If you have authorization use client.DefaultRequestHeaders.Authorization otherwise omit it
string myContent = "";
string myJson = <JsonQuery>;
using (HttpClient client = new HttpClient())
{
// If any authorization available
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenLabel.Text.Trim());
using (HttpResponseMessage response = await client.PostAsync("https:url", new StringContent(myJson, Encoding.UTF8, "application/json")))
{
using (HttpContent content = response.Content)
{
myContent = await content.ReadAsStringAsync();
}
}
}
Update
Content
string myJson = "{\"subject\": }";
URL
using (HttpResponseMessage response = await client.PostAsync("{{URL}}/v1/groups", new StringContent(myJson, Encoding.UTF8, "application/json")))
Header
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "");

Can't get a token from the Google API

I'm trying to exchange my authorization code for a token with the Google OAuth2 API for my Windows 8 app, but I keep getting HTTP 400 errors.
This is how I perform the request (simplified):
var url = "https://accounts.google.com/o/oauth2/token";
var body = "code=4/LEXF1iAVRZvfCfdQg9r1aFqoYDgV&client_id=904019870963.apps.googleusercontent.com&client_secret=[removed]&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code";
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.PostAsync(new Uri(url), new StringContent(body));
response.EnsureSuccessStatusCode();
Visual Studio usually simply gives me a HTTP 400 bad request error, when I try the same thing in Fiddler I also get an HTTP 400 error, but with this as content:
21
{
"error" : "invalid_request"
}
0
I read all the documentation about Google OAuth, I searched on Google and StackOverflow for this issue, I tried changing all different sorts of things in my code (UrlEncode, etc.), I used the Google API Playground to see what kind of requests it performs and compared it with my own requests (couldn't find a difference except for the return URL, the auth code and the user-agent). No matter what I do, I just can't get this working, I've been stuck for hours already.
Can anyone help me out here?
Read the body content to get the error json you noticed in Fiddler.
HttpClient httpClient = new HttpClient();
var response = httpClient.PostAsync(new Uri(url), new StringContent(body)).Result;
var content = response.Content.ReadAsStringAsync().Result;
content now holds :
{
"error" : "invalid_request"
}
You could project the error in an object, by specifing your error type like: response.Content.ReadAsAsync().Result
For the invalid request part, you should play with UrlEncode. I know you say you tried it, but applying it at the right spots really solves your problem.
var body = "code="+WebUtility.UrlEncode("4/LEXF1iAVRZvfCfdQg9r1aFqoYDgV")+
"&redirect_uri="+WebUtility.UrlEncode("https://yoursite...")+
"&client_id=904019870963.apps.googleusercontent.com" +
"&scope=" +
"&client_secret=********" +
"&grant_type=authorization_code";
HttpClient httpClient = new HttpClient();
var response = httpClient.PostAsync(new Uri(endpoint),
new StringContent(body, Encoding.UTF8, "application/x-www-form-urlencoded")).Result;
This is the code that works for me. Should work for you also.