Can't get a token from the Google API - authentication

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.

Related

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.

How to read the html out of spa website with asp.net.core

As there are no API for this I need to get the HTML of the following website with WebClient response method.
HttpClient client = new HttpClient();
try
{
HttpResponseMessage response = await client.GetAsync("https://www.datawrapper.de/_/UPFwh/");
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
}
catch(HttpRequestException e)
{
}
client.Dispose(true);
The problem is, when I do that I get only the source code of normal javascripts of this single page application and not the real HTML.
Anybody know how to grab the real html with
I profiled the traffic a bit and it looks like the response from that URL you're using is indeed mainly a script, which eventually will load the rest of the website.
Looking through the details the HTML part of the main data seems to be available under a different URL:
https://datawrapper.dwcdn.net/UPFwh/34/
Consider using that instead. Hope this helps!

Trustpilot Api - Get Private Product Review always returns Unauthorised response status

I hope someone can help me.
I am trying to retrieve a Product Review for a product using the Trustpilot Api's and am having some success but not getting the results I would expect.
The approach I have taken is as follows:
Get an OAUTH2 token - (Returns a successful response)
Retrieve my business units from a config file and for each business unit get the product reviews using the endpoint: https://api.trustpilot.com/v1/private/business-units/{business-unit}/review?token={OAUTH2 token from step 1} - (Returns a successful response)
For each product review I attempt to retrieve the product review detail. For this I have a couple of options.
(i) Each product review has meta-links and so I can get the product review using the corresponding meta-link and tagging the apikey on e.g. https://api.trustpilot.com/v1/reviews/1234567890abcdefg?apikey={apikey} where the apikey is the one provided up when I registered for a developer account - (Returns a successful response)
(ii) Call the endpoint as documented in the developers.trustpilot.api website (https://developers.trustpilot.com/product-reviews-api#get-private-product-review) : https://api.trustpilot.com/v1/private/product-reviews/{reviewId} - (Returns an Unauthorised status code)
For option (ii) above I have tried multiple ways of passing the apikey (according to the documentation, the endpoint requires the apikey as authorisation.
I am using C# as the language for accessing the Trustpilot apis so the following snippets are how I have tried to call the method.
Set the GetProductReview endpoint as follows:
var url = $"https://api.trustpilot.com/v1/private/product-reviews/" + review.Id.ToString();
using (var client = new HttpClient())
{
var uri = new Uri(url, UriKind.Absolute);
client.BaseAddress = uri;
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new system.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("apikey", apiKey);
try
{
var response = client.GetAsync(uri).Result;
.
.
.
In the above code snippet, the apikey is passed in to the method and passed to the endpoint as a RequestHeader value.
Set the endpoint as follows:
var url = $"https://api.trustpilot.com/v1/private/product-reviews/" + review.Id + $"?apikey={apiKey}";
and call the HttpClient as follows:
using (var client = new HttpClient())
{
var uri = new Uri(url, UriKind.Absolute);
client.BaseAddress = uri;
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
try
{
var response = client.GetAsync(uri).Result;
.
.
.
In both cases I receive an HttpStatus 401 - Unauthorized.
The documentation indicates that I should pass the apikey (which I have done in two different ways).
I have also tried calling the endpoint replacing the ?apikey={apiKey} with ?token={token} in case the documentation is incorrect and requires a token.
Additionally, I have also tried passing the token as a RequestHeader value and receieve the same result (Unauthoirised)
I would really like to use the endpoint:
https://api.trustpilot.com/v1/private/product-reviews/{review}
as this returns more information (for example the sku which would allow me to get access back to the product).
Can anyone please tell me where I am going wrong here?
Thanks in advance
The documentation for the /v1/private/product-reviews/{reviewId} endpoint is indeed incorrect, since it actually requires a Business user OAuth Token instead of an API Key.
In this case, you have two options (and the first one you have used before for the /v1/private/business-units/{businessUnitId}/reviews endpoint):
You can pass the access token in the query string: /v1/private/product-reviews/{reviewId}?token={token}. You mentioned you have tried this. Maybe it did not work for you because your token expired before you tried this approach. Can you try again after refreshing the token?
You can also pass the access token as a Bearer authorization header:
var url = $"https://api.trustpilot.com/v1/private/product-reviews/{review.Id.ToString()}";
using (var client = new HttpClient())
{
...
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
...
}
In any case, you caught an error in the documentation that should be fixed soon. As a rule of thumb, all private endpoints (the ones that have /private/ in the path) require a Business user OAuth Token.
EDIT: The documentation for the /v1/private/product-reviews/{reviewId} endpoint has been fixed. Now it shows that a Business user OAuth Token is required.

How to call API URL windows 8 C#

I am new to windows 8. I want to call api url and the response will be return in terms of json. My Question is how to call below api url in my windows 8 code with c#.
API URL: http://scwin8dashboard.cloudapp.net/shell/~/analytics/reports/reports.ashx?fff=0&report=CampaignCategoriesOverview&languages=&sites=&startDate=20080101&endDate=20121114&addLastModified=true
please help
var uri = "http://scwin8dashboard.cloudapp.net/shell/~/analytics/reports/reports.ashx?fff=0&report=CampaignCategoriesOverview&languages=&sites=&startDate=20080101&endDate=20121114&addLastModified=true";
var client = new HttpClient();
var response = await client.GetStringAsync(uri);
var parser = JsonObject.Parse(response);
For more informations about Http requests see this page.
For JSON related classes see the Windows.Data.Json namespace.

.NET HttpClient hangs after several requests (unless Fiddler is active)

I am using System.Net.Http.HttpClient to post a sequence of requests from a console application to a REST API and to deserialize the JSON responses into strongly-typed objects. My implementation is like this:
using (var client = new HttpClient())
{
var content = new StringContent(data, Encoding.UTF8, "text/html");
var response = client.PostAsync(url, content).Result;
response.EnsureSuccessStatusCode();
return response.Content.ReadAsAsync<MyClass>().Result;
}
However, I am experiencing a problem very similar to one described in this question, whereby everything works fine when the requests are routed via Fiddler, but it hangs after the 4th or 5th request when Fiddler is disabled.
If the cause of the problem is the same, I assume I need to do something more with HttpClient to get it to fully release its resources after each request but I am unable to find any code samples that show how to do this.
Hoping somebody can point me in the right direction.
Many thanks,
Tim
You are not disposing of the HttpResponseMessage object. This can leave open streams with the server, and after some quota of streams with an individual server is filled, no more requests will be sent.
using (var client = new HttpClient())
{
var content = new StringContent(data, Encoding.UTF8, "text/html");
using(var response = client.PostAsync(url, content).Result)
{
response.EnsureSuccessStatusCode();
return response.Content.ReadAsAsync<MyClass>().Result;
}
}