GET call to a Google API responds with "Unauthorized" - c#

UPDATE: Figured this out. I DID need to add the authorization header as answered below but I also believe the issue for my particular use case is that the access token (which I verified through Postman) required more scopes to authenticate me fully, which makes sense since this API contains surveys that I am trying to access, which are also linked to a Google account. Once I added the extra scopes needed to access the surveys to the token request along with the authorization header code below I was able to connect successfully.
More info on adding scopes to C# code can be found here: http://www.oauthforaspnet.com/providers/google/
Hope this helps anyone running into similar issues. Thanks all!
I am trying to make a GET call to a Google API but it keeps responding with "Unauthorized" while I am logged in to Gmail. I've already implemented Google+ Sign-In in StartUp.Auth.cs and even saved the access token for later use.
So how do I get the HttpClient to authorize me?
I have an access token available but I do not know how to pass it in properly. I've seen examples with usernames and passwords, but I should not need to pass those parameters if I already have an access token? If anything, I should be able to have the user redirected to a login page instead if needed when I log out before running the solution.
What I am expecting when the project is run, is the result of the GET call to come back in the form of json but it always says I'm "Unauthorized" and I am probably missing 1 line of code somewhere...
Here is the code I am using:
using (HttpClient client = new HttpClient())
{
string _url = "https://www.googleapis.com/consumersurveys/v2/surveys?key={MY_API_KEY}";
client.BaseAddress = new Uri(_url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
using (HttpResponseMessage response = client.GetAsync(_url).Result)
{
if (response.IsSuccessStatusCode)
{
using (HttpContent content = response.Content)
{
var Content = content.ReadAsStringAsync();
ViewBag.GoogleResponse = Content.ToString();
}
}
else
{
// THIS IS ALWAYS UNAUTHORIZED!
ViewBag.GoogleResponse = response.StatusCode + " - " + response.ReasonPhrase;
}
}
}
Please help with ideas or suggestions. Thanks!

You need to pass the auth token in an Authorization Header:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

Have you ever gotten an response for this api/survey? If you were unable to get a response from the API by hitting it with Postman, you may have issues in the way you are targeting the API. The error being returned there seems like you weren't including the token in your request header. Did you click the Authorization tab below the request URL to add the OAuth token to your header? (Keep in mind that the {} characters need to be URL encoded)
Also, when you are referencing MY_API_KEY, is that analagous to your surveyId?
I don't have a lot of experience here, but I have a couple of suggestions :
1) I agree with Pedro, you definitely need to include the Authorization Header in your request.
2) If your MY_API_KEY is in fact the survey ID, you may be providing an incorrect URL (GoogleAPIs documentation indicates that it should be < http://www.googleapis.com/consumer-surveys/v2/surveys/surveyId >
Recommendation (after moving your API key to a string var named MY_API_KEY) :
string _url = "https://www.googleapis.com/consumersurveys/v2/surveys/";
client.BaseAddress = new Uri(_url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ViewBag.GoogleAccessToken);
using (HttpResponseMessage response = client.GetAsync(MY_API_KEY).Result)
{
if (response.IsSuccessStatusCode)
{
using (HttpContent content = response.Content)
{
var Content = content.ReadAsStringAsync();
ViewBag.GoogleResponse = Content.ToString();
}
}
Reference:
https://developers.google.com/consumer-surveys/v2/reference/
http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client

Related

C#: How to htttps get request with bearer token in header

Hello everyone my name is Taniguchi.
I've tried retrieving an entity from Dynamics 365 Finance and Operations and i did it on postman but now i having difficulties in asp.net core I was able to get the token but when i try to retrieve the entity the response gives me a html and this html leads me to the Dynamics 365 Finance and Operations Page.
My code:
`
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
const string environmentsUri = "https://trial-0z4qfj.sandbox.operations.dynamics.com/data/PartyContacts";
var response = httpClient.GetAsync(environmentsUri).Result;
var content = response.Content.ReadAsStringAsync().Result;
what am i doing wrong ? do i need to authenticate again ?
I suspect the Token you receive is not correct/complete.
I remember I faced the similar issue, I would request you to follow this blog post and try to receive Token as shown This shall help you solve your issue.
In addition I would recommend you use Organizaiton service with Webapi/Access Token. It will give you native library usage and you could query crm easily.
Try this blog for Orgservice
Seems like you are only using the parameter accessToken instead of the variable value. Depends on how you declared accessToken ofc. The rest seems fine.
Try:
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token.accessToken);

Asana API 403 Response in C#

I am trying to implement a Xamarin app that works with the Asana API.
I have successfully implemented the OAuth as documented in the Asana documentation here... at least I assume it is successful. I get an access token from the token endpoint in an HTTPResponse with HTTP Status "OK".
But then when I turn around and try to make an API call with that same access token, I get a 403 Forbidden error. I tried the same API call in my browser (after logging in to Asana), and it works fine, which leads me to believe that I do have access to the resource, I must have an issue with authorizing the request on my end.
The API call in question is (documented here): https://app.asana.com/api/1.0/workspaces.
My C# code is as follows (abbreviated to relevant parts, and assume that ACCESS_TOKEN contains the access token I got from the token exchange endpoint):
HttpClient client = new HttpClient();
client.BaseAddress = "https://app.asana.com/api/1.0";
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", ACCESS_TOKEN);
client.DefaultRequestHeaders.Add("Accept", "application/json");
And then I use this HttpClient (named client) in the following function:
// Returns a list of the Asana workspace names for the logged in user.
private async Task<List<string>> GetWorkspacesAsync()
{
List<string> namesList = new List<string>();
// Send the HTTP Request and get a response.
this.UpdateToken(); // Refreshes the token if needed using the refresh token.
using (HttpResponseMessage response = await client.GetAsync("/workspaces"))
{
// Handle a bad (not ok) response.
if (response.StatusCode != HttpStatusCode.OK)
{
// !!!THIS KEEPS TRIGGERING WITH response.StatusCode AS 403 Forbidden!!!
// Set up a stream reader to read the response.
// This is for TESTING ONLY
using (StreamReader reader = new StreamReader(await response.Content.ReadAsStreamAsync()))
{
// Extract the json object from the response.
string content = reader.ReadToEnd();
Debug.WriteLine(content);
}
throw new HttpRequestException("Bad HTTP Response was returned.");
}
// If execution reaches this point, the Http Response returned with code OK.
// Set up a stream reader to read the response.
using (StreamReader reader = new StreamReader(await response.Content.ReadAsStreamAsync()))
{
// Extract the json object from the response.
string content = reader.ReadToEnd();
JsonValue responseJson = JsonValue.Parse(content);
foreach (JsonValue workspaceJson in responseJson["data"])
{
string workspaceName = workspaceJson["name"];
Debug.WriteLine("Workspace Name: " + workspaceName);
namesList.Add(workspaceName);
}
}
}
// I have other awaited interactions with app storage in here, hence the need for the function to be async.
return namesList;
}
Finally found the answer. It looks like I was using HttpClient incorrectly; a subtle thing that should be equivalent, but is not due to the way it is implemented.
The answer
I needed to place the final slash at the end of the BaseAddress property of HttpClient, and NOT at the start of the relative address for the specific request. This answered question explains this.
To fix my code
I needed to change the setting up of the BaseAddress:
HttpClient client = new HttpClient();
client.BaseAddress = "https://app.asana.com/api/1.0/"; // FINAL SLASH NEEDED HERE
And remove the slash from the request's relative address:
// DO NOT put slash before relative address "workspaces" here
using (HttpResponseMessage response = await client.GetAsync("workspaces"))
Why I got the original error
When HttpClient combined the BaseAddress with the relative URI I specified in GetAsync(), it dropped off some of the base address, since the final slash was not included. The resulting address from combining the BaseAddress with the relative URI was a valid URL, but not a valid page/API call in Asana. Asana thus did an automatic redirect to a login page, which, of course, the rest of the API call would be forbidden from there.
How I discovered this
In debugging, I grabbed the access token returned during my app's authorization with Asana. I then recreated the request to the "/workspaces" API myself in Postman, and the request worked as expected. This confirmed that my authorization worked fine, and the issue must be with the specific request rather than the authorization. In debugging I then looked into the HttpResponseMessage, which has a property called RequestMessage, that includes the actual URL the GetAsync() made the request against. I observed the Login URL from Asana, rather than the BaseAddress I specified... which led me to the question/
answer linked above.
Hope this explanation helps anyone who comes across a similar error!

How do I send a post request to telegram API from C#?

I have my telegram application with app's api_id and app's api_hash.
I used TLSharp library for implementing my own things. But now I need to use this https://core.telegram.org/method/auth.checkPhone telegram api method, but it's not implemented in TLSharp library!
I don't mind doing it all manually, but I don't know how!
I know how you send post requests in C#, example:
var response = await client.PostAsync("http://www.example.com/index", content);
but in this specific case I don't. Because I don't know:
1) what link should I use for sending post requests? I couldn't find it on the telegram's website.
2) what content should I pass there? Should it be just "(auth.checkPhone "+380666454343")" or maybe the whole "(auth.checkPhone "+380666454343")=(auth.checkedPhonephone_registered:(boolFalse)phone_invited:(boolFalse))" ?
So, How do I sent this post request to the telegram api? (NOT telegram bot api!)
Try to use System.Net.Http like in this example (auth request to the server):
var user = new { login = "your login", password = "your pass" };
string json = JsonConvert.SerializeObject(user);
HttpContent content = new StringContent(json, Encoding.UTF8, "application/json");
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage();
request.RequestUri = new Uri("server route link"); // can be like https://a100.technovik.ru:1000/api/auth/authenticate
request.Method = HttpMethod.Post;
request.Content = content;
HttpResponseMessage response = await client.SendAsync(request);
responseText.Text = await response.Content.ReadAsStringAsync();
I think based on a brief look, that it would be more along the lines of your second example, e.g.:
var phonenumber = "0123456789";
var content =
$#"(auth.checkPhone ""{phonenumber}"")"+
"=(auth.checkedPhone phone_registered: (boolFalse) phone_invited:(boolFalse))";
var result = DoHttpPost("http://some.example.com/api/etc", content);
(note: I've not listed the actual mechanics of an HTTP Request here, as that is covered in plenty of detail elsewhere - not least in the other current answer supplied to you; DoHttpPost() is not a real method and exists here only as a placeholder for this process)
And since the payload of this appears to indicate the exact function and parameters required, that you'd just send it to the base api endpoint you use for everything, but I can't say for sure...
I do note they do appear to have links to source code for various apps on the site though, so perhaps you'd be better off looking there?

Using Azure Hybrid Connection to connect to internal Web API

Very new to Azure, and I have an internal web API on an internal address http://internal-server:182/api/policies. I have set up a Hybrid Connection internal-service.servicebus.windows.net. This is connected and working.
My struggle is getting the C# code working to connect and retrieve the data. After a number of days, I have reviewed various articles, videos etc and all seem more advanced than what I am trying to do, which is just call the Web API and read the JSON. I have tried to simplify the code but receive the error:
401 MalformedToken: Invalid authorization header: The request is missing WRAP authorization credentials.
At present I have the followed code:
using (var client = new HttpClient())
{
var url = "http://internal-service.servicebus.windows.net";
var tp = TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", "<key goes here>");
var token = tp.GetWebTokenAsync(url, string.Empty, true, TimeSpan.FromHours(1))
.GetAwaiter()
.GetResult();
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("ServiceBusAuthorization", token);
var response = client.GetAsync("/api/policies").Result;
string res = "";
using (HttpContent content = response.Content)
{
// ... Read the string.
Task<string> result = content.ReadAsStringAsync();
res = result.Result;
Label1.Text = res;
}
}
Any help or direction would be much appreciated? Once this code is working the Web App will be published as an Azure Web App.
Seems that your are not sending the right header.
First suggestion: intercept the call with a proxy like fiddler, to do that add a proxy config to your call to localhost port 8888, after this you can try some request and see the raw http you are sending to the server, you can also modify it until it works, once you have this modify your code until it send the same raw http.
You can find more info about this here:
Microsoft Azure CreateQueue using Simple REST Client
https://github.com/ytechie/event-hubs-sas-generator

OAuth Headers Twitter 1.1 C# Fetching Tweets

After Twitter deprecated their Twitter API 1.0, I've tried several methods in order to get the 1.1 API working for my Windows 8 application. However, what you see below is basically what I've ended up with:
public List<UserTweet.User> jsonFromTwitter;
private async void fetchTweet()
{
var jsonTwitter = new Uri("http://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=stackoverflow&result_type=recent");
HttpClient client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, jsonTwitter);
var oAuthHeader = "OAuth oauth_consumer_key=\"XXXXX\", oauth_nonce=\"XXXXX\", oauth_signature=\"XXXXX\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"1318622958\", oauth_token=\"XXXXX-XXXXXX\", oauth_version=\"1.0\"";
request.Headers.Add("Authorization", oAuthHeader);
var response = await client.SendAsync(request);
var responseString = await response.Content.ReadAsStringAsync();
jsonFromTwitter = JsonConvert.DeserializeObject<List<UserTweet.User>>(await client.GetStringAsync(responseString));
//listbox.ItemsSource = jsonFromTwitter;
}
However, this won't do much good, and it switches between mainly a couple of errors. One of them can be seen below, and the other one is "Could not authenticate user" or similar, basically there's something wrong with the headers as far as I've understood.
Anyone got any ideas on how to construct a working OAuth header for this? I'm clueless at the moment.
There's a lot more you need to do for the value assigned to the Authorization header - plain text won't work. The following pages in the Twitter OAuth documentation might help you get started in the right direction.
Twitter's Docs have a section on Authentication
Authorizing a Request
Creating Signatures

Categories

Resources