Getting Error 400 when using Authentication Broker in Win 8 App for Stackexchange API - vb.net

I'm trying to connect to StackExchange API using OAuth.
So far i've been able to get a token and retrive data that does not require authentication.
When i try do query that uses the authentication, i'm getting error 400 - Bad request.
Heres the code:
Dim Key As String = "(app_key)"
Dim RequestURL As String = "https://api.stackexchange.com/2.2/me/questions?access_token=" & Token & "key=" & Key & "&order=desc&sort=activity&site=stackapps"
Dim Handler As HttpClientHandler = New HttpClientHandler()
If Handler.SupportsAutomaticDecompression Then
Handler.AutomaticDecompression = DecompressionMethods.GZip Or DecompressionMethods.Deflate
End If
Dim HttpClient As HttpClient = New HttpClient(Handler)
Dim query = Await HttpClient.GetAsync(RequestURL)
If query.IsSuccessStatusCode = True Then
'(query.Content.ReadAsStringAsync())
End If
Tried using only key, only access token, or none in the request, but received the same error. Also tried adding "OAuth" header and "access_token":
HttpClient.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("OAuth", Token)
HttpClient.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("access_token", Token)
Any help appreciated.

Solved it! Turns out a was using the wrong key. I managed to make it work by using both access_token and key in the RequestUrl, not using the request headers.

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

asp.net core webapp - OAUTH2 AUTHORIZATION - 401 Error

i want to use the itwin api and i created a little asp.net core 3.1 webapp.
The Authorization endpoint: https://ims.bentley.com/connect/authorize works fine and i get a code.
Now i want to use the code to get the access token with this backend method:
string url = "https://ims.bentley.com/connect/token";
string clientID = "webapp-XXXXXXXXXXXXXXXXXXXXXX";
string secretID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
//string svcCredentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(clientID + ":" + secretID));
//string svcCredentials = Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(clientID + ":" + secretID));
string svcCredentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(clientID + ":" + secretID));
var nvc = new List<KeyValuePair<string, string>>();
nvc.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
nvc.Add(new KeyValuePair<string, string>("code", code));
nvc.Add(new KeyValuePair<string, string>("redirect_uri", "http://localhost:44343/signin-callback"));
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", svcCredentials);
HttpResponseMessage response = client.PostAsync(url, new FormUrlEncodedContent(nvc)).Result;
var token = response.Content.ReadAsStringAsync().Result;
}`
Everthing works fine but i get an 401 Error. Use i the wrong BASE64 encoding?
thank you for help.
I suggest trying the following:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", svcCredentials);
Based on the documentation for AuthenticationHeaderValue the first parameter is the scheme and we use Bearer.
You need to url-encode client_id and client_secret before using them for Basic authentication, as described in documentation
The client must authenticate using the HTTP Basic method and provide the url-encoded clientId and the clientSecret
This is also stated in OAuth specification
The client identifier is encoded using the
"application/x-www-form-urlencoded" encoding algorithm per
Appendix B, and the encoded value is used as the username; the client
password is encoded using the same algorithm and used as the
password.

Call authorized Web API using WebClient

After hours of searching the internet I decided to ask you guys for a little help.
I've written an Web API with couple of simple get/post methods. I'm using Individual user accounts authentication method.
Using the HttpClient I've managed to successfully call every AUTHORIZED get and post method as well as the /token endpoint used for generating authorization token.
The problem is that I must call these methods inside .NET Framework 3.5 project. So I've tried using WebClient to do this because I read that the HttpClient is not supported in .NET Framework 3.5.
GetAPIToken() METHOD generates Bearer token and it works.
private static string GetAPIToken(string userName, string password, string apiBaseUri)
{
using (WebClient client = new WebClient())
{
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
var response = client.UploadString(apiBaseUri + "/Token", "POST", "grant_type=password&username=" + userName + "&password=" + password);
var jObject = JObject.Parse(response);
return jObject.GetValue("access_token").ToString();
}
}
This GET method works when I remove [Authorize] attribute from the Web API but I can't make it work when authorized.
//GET ODRAĐENI POSTUPCI
private static string GetOdradjeniPostupci(int Id, string token)
{
string apiBaseUri = "http://localhost:60511/";
string serviceUrl = apiBaseUri + "api/ZOdradjeniPostupci";
using (WebClient client = new WebClient())
{
client.Headers.Clear();
client.Headers.Add("Content-Type", "application/json");
client.Headers.Add("Authorization", "Bearer " + token);
var response = client.DownloadString(serviceUrl + "/GetZOdradjeniPostupci?cZdrUst=" + Id.ToString());
return response;
}
}
I get error 401 unathorized no matter what I try. (Different combinations from the internet regarding Authorization header).
Hope you could give me any advice on how to solve this.
I would appreciate it a lot.
Thanks.

How to connect to Onedrive using MSAL?

I'm trying to connect to OneDrive using MSAL token but it's returning error="invalid_token", error_description="Auth error"
This is my code:
public static string[] Scopes = { "User.Read", "Files.Read", "Sites.Read.All" };
AuthenticationResult ar = await App.ClientApplication.AcquireTokenSilentAsync(Scopes);
WelcomeText.Text = $"Welcome {ar.User.Name}"; //Login OK here
//get data from API
HttpClient client = new HttpClient();
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Get, "https://api.onedrive.com/v1.0/drives");
message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", ar.Token);
HttpResponseMessage response = await client.SendAsync(message);
string responseString = await response.Content.ReadAsStringAsync();
Anyone know what I'm doing wrong ?
The direct API endpoint (api.onedrive.com) doesn't support access tokens generated from MSAL, only tokens generated from MSA. If you are using MSAL, you should use the Microsoft Graph API (graph.microsoft.com) to access OneDrive files for both personal and business users.
You already got your answer long time back but I hope this link will be helpful for someone else in future.
https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/onedrive

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.