Google Drive API bad request from C# but fine from Postman - c#

I'm using this request code from C# and getting a Bad Request result:
public class GoogleDriveManager
{
private static readonly HttpClient Client = new HttpClient();
private const string Access = "ACCESS";
public GoogleDriveManager()
{
Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Access);
}
public async Task<HttpResponseMessage> GetFilesAsync(string driveId)
{
var url =
$"https://www.googleapis.com/drive/v3/files?driveId={driveId}&includeItemsFromAllDrives=true&corpora=true&supportsAllDrives=true";
var result = await Client.GetAsync(url);
return result;
}
}
But when I make the same sort of request from Postman, it works great:
GET https://www.googleapis.com/drive/v3/files?driveId=DRIVEID&includeItemsFromAllDrives=true&corpora=drive&supportsAllDrives=true
(Authorization Bearer Token, with token value the same as the one used above)
What am I doing wrong on the C# side?

According to API documentation supported values for corpora are:
user
domain
drive
allDrives
Your Postman example has corpora=drive but your C# example shows corpora=true.

Related

How to use access tokens to get authorization to access REST APIs

I have an HttpClient that I am using for a REST API. I get the access token from the server but I do not have permission to use the REST APIs. The response is Error: Unauthorized
First, Using getAccessToken() method, I get the access token.
public static async Task<string> getAccessToken()
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Referer", "http://admin.altrabo.com/");
var tokenClient = new TokenClient()
{
client_Id= -1,
username= "admin",
password= "Main#dm!n",
grant_Type= "Main#dm!n",
externalProvider= 1,
};
HttpResponseMessage response = await client.PostAsJsonAsync<TokenClient>("https://api.altrabo.com/api/v1/token", tokenClient);
var json = JsonSerializer.Deserialize<AccessToken>(response.Content.ReadAsStringAsync().Result);
return json.access_token;
}
which returns the access token.
Then, using the verifyToken() method, I verify the access token.
public static async Task<string> verifyToken(string access_token)
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + access_token);
HttpResponseMessage response = await client.GetAsync("https://api.altrabo.com/api/v1/verifyToken");
return response.ReasonPhrase;
}
returns OK
But when I want to get access to API, I encounter Error: Unauthorized.
For example when I want to get the list of airports:
public static async Task<string> ListAirports()
{
var client = new HttpClient();
return await client.GetStringAsync("https://api.altrabo.com/api/v1/BaseData/GetAirports?pageSize=1000&pageNumber=1");
}
The API documentation is available at
https://www.getpostman.com/collections/51cd9e7f5f6ebafa8c48‎
Add the token to the request to get the airports, in the same manner you do, as when you verify the token.
public static async Task<string> ListAirports(string access_token)
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + access_token);
return await client.GetStringAsync("https://api.altrabo.com/api/v1/BaseData/GetAirports?pageSize=1000&pageNumber=1");
}
you have to check the documentation of the rest-api for what authorization-method the api requires. Maybe its username/password or something.
https://username:token#your-api.com

Body not sent when using Bearer Authentication

I have a winform client that consumes data from a Python Flask API using Zalando's Connexion and OpenAPI 3.
The client uses Net Framework 4.8. When I send a POST request with Authorization header, the body doesn't get sent, so I get an error 400 from the server. I've inspected received data on API side, also I created a blank project with Flask only that just outputs what it receives as requests, and the body is not there. Inspecting the content on Visual Studio shows the body, but it never reaches the API server.
If I don't put the Authorization header it works ok. It also works ok for GET, WITH the header.
This is how I set the token on client side:
public void SetToken(string token) {
Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
This is my default constructor for the client:
public class RestClient{
private readonly HttpClient Client;
public RestClient {
Client = new HttpClient();
Client.DefaultRequestHeaders.Accept.Clear();
Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
}
I've searched a lot before asking here for someone with my same problem but couldn't find any post.
I also see that almost all examples use form/urlencoded for POST instead of application/json but I guess that's simple a choice for the format, doesn't seem as a requirement when using authentication.
I'm using:
Visual Studio 2019
Net Framework 4.8 (tried with 4.7 too)
Python 3.7.2
Flask 1.1.1
Connexion 2.3.0
Also tried from an API test suite with Bearer Authorization created on Python using requests library and it works ok from there...
Edit:
As requested adding my post code:
public HttpResponseMessage Post(string path, HttpContent content, int maxRetries = 0)
{
if (maxRetries < 0)
{
throw new ArgumentException("maxRetries cannot be less than 0");
}
int attemptsMade = 0;
int maxAttempts = maxRetries + 1;
bool workCompletedSuccessfully = false;
bool attemptsRemain = true;
HttpResponseMessage response = null;
while (!workCompletedSuccessfully && attemptsRemain)
{
attemptsMade++;
attemptsRemain = attemptsMade < maxAttempts;
try
{
response = Client.PostAsync(path, content).GetAwaiter().GetResult();
if (response.IsSuccessStatusCode)
{
workCompletedSuccessfully = true;
}
}
catch (Exception e)
{
if (!attemptsRemain)
{
throw e;
}
}
}
return response;
}
And this is how I call it from the service:
private const string PATH = "person";
public PersonService(RestClient rest)
{
_rest = rest;
}
public HttpResponseMessage AddNew(Person person)
{
var personJson = JsonConvert.SerializeObject(person);
using (var content = new StringContent(personJson, Encoding.UTF8, "application/json"))
{
var result = _rest.Post($"api/{PATH}", content);
return result;
}
}
Does your bearer token (the string you pass to SetToken method) contain newlines? This can cause that problem.

Xamarin Android with fitbit api- Add Authorization to header

I have a xamarin android application that is connecting to fitbit through their API and xamarin.auth, I have the access token but am getting an unauthorized code when trying to GET the json response. I have tried to add the access token to the url but it did not work.
This is my code:
if (e.IsAuthenticated)
{
var request = new OAuth2Request("GET", new System.Uri("https://api.fitbit.com/1/user/-/profile.json?access_token=" + e.Account.Properties["access_token"]), null, e.Account);
request.AccessTokenParameterName = e.Account.Properties["access_token"];
string type = e.Account.Properties["token_type"];
var response = await request.GetResponseAsync();
var json = response.GetResponseText();
}
I can not figure out how to add the authorization to the header of the OAuth2Request.
Any help is much appreciated!
So I ended up adding a Custom Request class to extend the OAuth2Request class and added another GetResponseAsync function that takes the access token as a parameter. I then add the Authorization to the header and leave the rest of the function as is. Not sure if there's a way of doing this with Xamarin.Auth library the way it is, but it worked for me.
public class CustomRequest : OAuth2Request{ //..
public virtual async Task<Response> GetResponseAsync(string accessToken){//..
httpRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

How can I execute an url call from C# code on a ASP website on a ASCX page?

I need to call a Custom protocol (something like: "custom:signDocs?param1=value?param2=value") that is registered on a client.
I have a working one that is executed via JavaScript on a button click.
But I need to call the url to execute the program I have on the clients pc.
The program is for signing documents and sending them back to the server, and, in the code I have a 15min timer that waits for the status of the documents to change to signed then it shows the documents to the user.
I also tried using webrequest:
//Method that uses the webrequest
{
System.Net.WebRequest.RegisterPrefix("customProtocolName", new PrototipoIDPTRequestCreator());
System.Net.WebRequest req = System.Net.WebRequest.Create(protocolUrlWithParams);
var aux = req.GetResponse();
}
internal class CustomRequestCreator : System.Net.IWebRequestCreate
{
public WebRequest Create(Uri uri)
{
return new CustomWebRequest(uri);
}
}
class CustomWebRequest: WebRequest
{
public override Uri RequestUri { get; }
public CustomWebRequest(Uri uri)
{
RequestUri = uri;
}
}
But this does nothing, I do not know it its even the right path...
Does anyone know of a way to accomplish this?
You can use HttpClient from System.Net.Http like the following example.
Simple get call from a test api endpoint.
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("YOUR_BASE_URL"); //https://localhost:8000
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync("api/test"); //api uri
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
}
Note: For more details refer, HttpClient Doc

C# HttpClient 307 Destiny 2 SearchUser API

I am working on a library for the Destiny 2 API and I am running into a problem at this spot. I wrote an extension for the HttpClient.GetAsync so that I can do HttpClient.GetAsync<T> and I am finding that in this extension I am not getting a success message because I get a
307 Temporary Redirect
I have run this same API request into Postman using my same api key and same path request and Postman doesn't get an error.
Extension Code:
public async static Task<T> GetAsync<T>(this HttpClient Web, String Path)
{
var result = await Web.GetAsync(Path);
if (result.IsSuccessStatusCode)
{
var body = await result.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(body);
}
else
{
return default(T);
}
}
HttpClient Creation at creation of root ApiClass:
private HttpClient _Web { get; set; } = new HttpClient(new HttpClientHandler()
{
AllowAutoRedirect = true
});
So after beating my head for awhile I found that I was passing this string string path = $"User/SearchUsers?q={q}"; when it wanted this string string path = $"User/SearchUsers/?q={q}"; notice the slash after SearchUsers... Their API I think is just misconfigured and that was very annoying..

Categories

Resources