Obtaining a token using IHttpclientFactory - c#

I've written the code below in IhttpclientFactory. For some reasons, the code is not returning a token. oauth is returning null.
I will appreciate it if someone would kindly have a look and tell me where I've gone wrong. thank you
private async Task<OAuth>Authenticate()
{
//build request
var request = new HttpRequestMessage(HttpMethod.Post, "/oauth/token");
request.Content = new StringContent(JsonSerializer.Serialize(new OAuth() {grant_type="client_credentials",client_id="",client_secret=""}));
request.Content.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/x-www-urlencoded");
//build client
var client = _clientFactory.CreateClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/+json"));
// send the request
var response = await client.SendAsync(request);
OAuth oauth = null;
if (response.IsSuccessStatusCode)
{
var responseStream = await response.Content.ReadAsStringAsync();
//deserialise
var oAuth = Newtonsoft.Json.JsonConvert.DeserializeObject<OAuth>(responseStream);
}
return oauth;
}
}

You've got two different OAuth variables 'oauth' and 'oAuth'. C# identifiers are case-sensitive.
Should be something like
if (!response.IsSuccessStatusCode)
{
throw new InvalidOperationExeption($"OAuth Request Failed With Status code {response.StatusCode}");
}
var responseString = await response.Content.ReadAsStringAsync();
var oAuth = Newtonsoft.Json.JsonConvert.DeserializeObject<OAuth>(responseString);
return oAuth;

Related

How to add parameter in the web API while calling in C#

I have given below the sample code, I am calling web API but I am struggling to pass the parameter in the console application.
C# code:
HttpClient client = new HttpClient();
var responseTask = client.GetAsync("<web api name>");
responseTask.Wait();
HttpRequestMessage rm = new HttpRequestMessage();
var headers = rm.Headers;
client.DefaultRequestHeaders.Add("client_id", "1234xv");
client.DefaultRequestHeaders.Add("client_secret", "7dfdfsd");
if (responseTask.IsCompleted)
{
var result = responseTask.Result;
if (result.IsSuccessStatusCode)
{
var messageTask = result.Content.ReadAsStringAsync();
messageTask.Wait();
Console.WriteLine("Message from Web API:" + messageTask.Result);
Console.ReadLine();
}
}
You were making the GET call much early, even before adding the parameters to the HTTP headers. You need to add the params and then call the GetAsync().
See the modified code below,
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Add("client_id", "1234xv");
client.DefaultRequestHeaders.Add("client_secret", "7dfdfsd");
var responseTask = client.GetAsync("http://your api url");
responseTask.Wait();
if (responseTask.IsCompleted)
{
var result = responseTask.Result;
if (result.IsSuccessStatusCode)
{
var messageTask = result.Content.ReadAsStringAsync();
messageTask.Wait();
Console.WriteLine("Message from Web API:" + messageTask.Result);
Console.ReadLine();
}
}
}

HTTP PUT Request Body Found Null In Web API Controller

I am trying to send a request with HTTP Verb [HttpPut] which reached to my controller but param which I have sent is Null. Have seen lot of stack Overflow same thread and tried out but cannot figure out... Weird!
Class I have Serialized
Content requestContent = new Content();
requestContent.Name = "Name";
requestContent.Value = "Value";
Here is my request body
private readonly HttpClient _httpClient;
public GetAzureResponseClient(HttpClient httpClient)
{
_httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
}
var requestBody = JsonConvert.SerializeObject(requestContent);
var uri = new Uri("http://localhost:64288/api/ConnectUs/TestMethod");
var response = _httpClient.PutAsJsonAsync(uri, new StringContent(requestBody, Encoding.UTF8, "application/json")).Result;
client.DefaultRequestHeaders.Add("Authorization", "Basic" + "YourAuthKey");
var responseFromServer = await response.Content.ReadAsStringAsync();
My Web API Controller
public ActionResult<Content> TestMethod([FromBody]Content param)
You dont need to rewrap the object as JSON when using PutAsJsonAsync:
HttpClient client = new HttpClient();
var uri = new Uri("http://localhost:64288/api/ConnectUs/TestMethod");
var response = await client.PutAsJsonAsync(uri, requestContent); // LOOK HERE
client.DefaultRequestHeaders.Add("Authorization", "Basic" + "YourAuthKey");
var responseFromServer = await response.Content.ReadAsStringAsync();
you don't need extra serialization and you have to call the Async method with 'await'.
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Basic" + "YourAuthKey");
var uri = new Uri("http://localhost:64288/api/ConnectUs/TestMethod");
var response = await client.PutAsJsonAsync(uri, requestContent);
var responseFromServer = await response.Content.ReadAsStringAsync();
https://learn.microsoft.com/en-us/previous-versions/aspnet/hh944690(v%3Dvs.118)
PutAsJsonAsync will serialize the given object of type T, try PutAsync instead
https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.putasync?view=netframework-4.8

why An error is created when creating the token

public static void CreateToken()
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("grant_type", "client_credentials");
var UserPassJson = "{\"username\": \"mucode\",\"password\": \"mypassword\"}";
HttpContent content = new StringContent(UserPassJson, Encoding.UTF8, "application/json");
var response = client.PostAsync(new Uri("https://api.sandbox.paypal.com/v1/oauth2/token"), content).Result;
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
string responseString = responseContent.ReadAsStringAsync().Result;
Console.WriteLine(responseString);
}
}
why response.IsSuccessStatusCode Showing status code 401? What causes the malfunction?
What action does cause success?
The documentation specifies that you should pass the username and password using basic authentication and that you should pass a form-encoded body containing grant_type=client_credentials.
At the moment your code adds grant_type as a header, and posts the username and password as a JSON object in the body.
Correcting your code to do it the way the documentation says, we get:
HttpClient client = new HttpClient();
byte[] authBytes = System.Text.Encoding.ASCII.GetBytes("mucode:mypassword");
string base64Auth = Convert.ToBase64String(authBytes);
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", base64Auth);
HttpContent content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("grant_type", "client_credentials") });
var response = client.PostAsync(new Uri("https://api.sandbox.paypal.com/v1/oauth2/token"), content).Result;
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
string responseString = responseContent.ReadAsStringAsync().Result;
Console.WriteLine(responseString);
}
P.S. I recommend reading You're using HttpClient wrong and it is destabilizing your software and the follow-up You're (probably still) using HttpClient wrong and it is destabilizing your software. I also recommend making this method async and making the chain all the way up async too.

Cant get Authorized with my API that has a JWT authentication Im Working With Xamarin

Well Im new in Xamarin and I'm developing and App, the authentication is JWT based.
Im using a HttpClient and setting the AuthenticationHeaders but It always returns Unauthorized when I try it on Postman it Works but I can't make it work in my app.
Here is how im trying to do it:
var client = new HttpClient(new HttpClientHandler());
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("JWT", accessToken);
client.BaseAddress = new Uri(urlBase);
var url = string.Format("{0}{1}", servicePrefix, controller);
var response = await client.GetAsync(url);
Try something like this
using (var client = new HttpClient())
{
var uri = new Uri(string.Format($"{<yourURLString>}", string.Empty));
var jsonTransport = "";
var jsonPayload = new StringContent(jsonTransport, Encoding.UTF8, "application/json");
//client.DefaultRequestHeaders.Add("Content-type", "application/json");
client.DefaultRequestHeaders.Add("Authorization", "JWT " + accessToken);
var response = await client.PostAsync(uri, jsonPayload);
string responseContent = await response.Content.ReadAsStringAsync();
}
then deserialize the responseContent to your object using JsonConvert.DeserializeObject
Note: Below are code samples, edit to your own objects
SubscriptionResponse profileResponse = JsonConvert.DeserializeObject<SubscriptionResponse>(responseContent);
then if your method returns something, use the return statement. Something like this
return profileResponse.Data.Subscriptions;
If you're using a get, this could be a guide
var uri = new Uri(string.Format($"{<yourURLHere>}", string.Empty));
client.DefaultRequestHeaders.Add("Authorization", "JWT " + accessToken);
var httpResponse = await client.GetAsync(uri);
var responseContent = await httpResponse.Content.ReadAsStringAsync();
then deserialize your string response
Note: this is a sample - edit to your model (You may use PostMan to get the response format in JSON and model it in C#)
var UserDetailResponse = JsonConvert.DeserializeObject<UserDetail>(responseContent);
return UserDetailResponse;

Adding authorization to the headers

I have the following code:
...
AuthenticationHeaderValue authHeaders = new AuthenticationHeaderValue("OAuth2", Contract.AccessToken);
string result = await PostRequest.AuthenticatedGetData(fullUrl, null, authHeaders);
return result;
...
public static async Task<string> AuthenticatedGetData(string url, FormUrlEncodedContent data, AuthenticationHeaderValue authValue)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authValue.Parameter);
HttpResponseMessage response = await client.PostAsync(new Uri(url), data);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
return responseBody;
}
The response = await part just continues an ongoing loop and nothing happens. Any ideas what I am doing wrong?
The question really is, how do I send the following header:
Authorization: OAuth2 ACCESS_TOKEN
to an external web api
I struggled with this. I kept getting an error saying "invalid format" because I have a custom implementation and the Authorization header is validated against certain standards. Adding the header this way however worked:
var http = new HttpClient();
http.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "key=XXX");
This line
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(authValue.Parameter);
Will produce this header value
Authorization: ACCESS_TOKEN
Where ACCESS_TOKEN is the value of authValue.Parameter. You want to assign the value you passed instead to get the required header
client.DefaultRequestHeaders.Authorization = authValue;
Will produce
Authorization: OAuth2 ACCESS_TOKEN
Had a similar issue when getting AuthenticationHeaderValue to work with my requests.
I was also using JWT JsonWebToken from GitHub.
I was able to get a token from the API, but was struggling to use it in other GETs and POSTs.
var jwt = JsonWebToken.Encode(token, APISECRET, JwtHashAlgorithm.HS256);
var tk = GetTokenFromApi(); // basically returns an encrypted string.
Manually using WebRequest:
Which worked fine.
request.ContentType = "application/json";
request.Method = "POST";
request.Headers.Set("Authorization", string.Format("Bearer {0}", tk));
When we switched to an HttpClient, and used the AuthenticationHeaderValue, could not figure out how to set it up correctly.After looking at the request string, i saw it added the "Authorization" for me. Played around with parameters, and this finally this worked.
var authenticationHeaderValue = new AuthenticationHeaderValue("Bearer", tk);
Maybe intresting for other people. Since I searched on this for a long time. But you have to save your cookies also and give it with your next request. First this is how i got my authentication code and hold my cookies in a static variable (in the first time i call this method I give an empty value to token).
public static CookieContainer CookieContainer;
public static async Task<string> Post<TRequest>( TRequest requestBody, string path, string token = "")
{
var baseUrl = new Uri($"urlFromApi");
CookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = CookieContainer })
using(var client = new HttpClient(handler){BaseAddress = baseUrl})
{
client.DefaultRequestHeaders.ConnectionClose = false;
if (!string.IsNullOrWhiteSpace(token))
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", $"{token}");
}
ServicePointManager.FindServicePoint(client.BaseAddress).ConnectionLeaseTimeout = 60 * 1000; //1 minute using (var content = new ByteArrayContent(GetByteData(requestBody)))
using (var content = new ByteArrayContent(GetByteData(requestBody)))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await client.PostAsync(String.Empty, content);
return await GetResponseContent(response);
}
}
}
After this if I do any request to the api I include the cookies (token is what you get from the first response as a result)
public static async Task Get(string path, string token = "")
{
var baseUrl = $"https://innoviris-ai.collibra.com/rest/2.0{path}";
using (var handler = new HttpClientHandler() { CookieContainer = CookieContainer })
using (var client = new HttpClient(handler) {BaseAddress = new Uri(baseUrl)})
{
client.DefaultRequestHeaders.ConnectionClose = false;
if (!string.IsNullOrWhiteSpace(token))
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", $"{token}");
}
ServicePointManager.FindServicePoint(client.BaseAddress).ConnectionLeaseTimeout = 60 * 1000; //1 minute
var response = await client.GetAsync(String.Empty);
return await GetResponseContent(response);
}
}
In your code you are doing this:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", $"{token}");
I think the following should work the same manner without using string interpolation:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
This is because the string interpolation is just generating a string with the token in it!

Categories