Having difficulty getting a 200 response back from SendAsync for an HttpPost. This is for a multi-phase authentication using a basic authentication token to get a bearer token which is then used to get an accessKeyId and accessKeySecret which is then used to get a usable accessToken.
This is the format that is expected (provided by the vendor). I believe the code I have written handles the Header data correctly, but I am not sure about the body. When testing with Restlet or Postman the body must be entered exactly as shown. I think when the quoted tag and value are placed in C# the quotes are being lost in translation; see code below this section.
*************************From the Vendor*****************************
With a bearer token an access key can now be created using endpoint
https://xxxxxxxxxxxx/x-keys`
a.POST Request:
i. Header:
1. Authorization: bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9….
2. Content-Type: application/json
ii. Body:
1. {
2. "userId": "xxxxxxxxx-xxxxx-xxxx-xxxxx-xxxxxxxxxxxx",
3. "tenantId": "xxxxxxxxx-xxxxx-xxxx-xxxxx-xxxxxxxxxxxx"
4. }
>String newBearerToken = "bearer " + bearerToken;
>var cl = new HttpClient();
>cl.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
>cl.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", newBearerToken);
>var nvc = new List<KeyValuePair<string, string>>();
>nvc.Add(new KeyValuePair<string, string>("\"" + "userId" + "\"", "\"" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "\""));
>nvc.Add(new KeyValuePair<string, string>("\"" + "tenantId" + "\"", "\"" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "\""));
>var req = new HttpRequestMessage(HttpMethod.Post, "https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/-keys") { Content = new FormUrlEncodedContent(nvc) };
>var result = await cl.SendAsync(req);
I expect a response body with new access tokens and an HttpResponse of 200 but this is what is returned:
"result {StatusCode: 302, ReasonPhrase: '', Version: 1.1, Content:
System.Net.Http.StreamContent, Headers: { Content-Security-Policy:
default-src https: data: 'unsafe-inline' 'unsafe-eval';
connect-src...."
The authentication header should be the following...
new AuthenticationHeaderValue("Bearer", newBearerToken);
not "Authorization" if you're using bearer tokens
Your current implementation is doing the following
Authorization: Authorization bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9
Remove the bearer from the token too
String newBearerToken = bearerToken;
Related
I need help ...
When I use Postaman the 2 requests I make work correctly, but this code of mine only returns me the authentication correctly but when I create a new request, it does not return anything. The response_1 content returns this error: "{" error_code ":" platform.web_application "," correlation_id ":" d7em3oxz7ng6kh9qx977l3904 "," description ":" HTTP 404 Not Found "," description_translated ":" HTTP 404 Not Found ", "properties": null, "business_error": false} "
and the ResponseUri of response_1 is concatenated with that of the authentication. I can't find the error.This is the c# code
var client = new RestSharp.RestClient(url + #"/authentication/sign_in");
var request = new RestSharp.RestRequest(RestSharp.Method.POST);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", request.AddJsonBody(new { user = admUserPass[0], password = admUserPass[1] }), RestSharp.ParameterType.RequestBody);
ServicePointManager.SecurityProtocol = (SecurityProtocolType)768 | (SecurityProtocolType)3072;
RestSharp.IRestResponse response = client.Execute(request);
//response.StatusCode = "OK"
request.Resource = url + #"/admin/users";
request.Method = RestSharp.Method.GET;
foreach (var cookie in response.Cookies)
{
request.AddCookie(cookie.Name, cookie.Value);
}
request.AddHeader("content-type", "application/json");
request.AddHeader("Accept", "application/json");
RestSharp.IRestResponse response_1 = client.Execute(request);
Create a new Request before executing the second client.Execute(...)
OK I found the solution, my code is right but I am working to consume the Octane ALM API rest.
adding this line in the request header "request.AddHeader("ALM_OCTANE_TECH_PREVIEW "," true ");"
The request is working correctly. There is a discussion at this link https://community.microfocus.com/adtd/alm_octane/f/ngabetageneralbetaforum/161440/alm_octane_tech_preview-header-issue
I am new to the C# world, and can't for the life of me figure out how to get around this error. I am trying to make a simple get request using a platform API key. I have built out the API connection in Google App Script on the same laptop, and it works fine, but when trying to build out the same API in C#, it is returning:
{StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
Date: Sun, 13 Mar 2022 02:41:29 GMT
Transfer-Encoding: chunked
Connection: close
CF-Chl-Bypass: 1
Permissions-Policy: accelerometer=(),autoplay=(),camera=(),clipboard-read=(),clipboard-write=(),fullscreen=(),geolocation=(),gyroscope=(),hid=(),interest-cohort=(),magnetometer=(),microphone=(),payment=(),publickey-credentials-get=(),screen-wake-lock=(),serial=(),sync-xhr=(),usb=()
Cache-Control: private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0
X-Frame-Options: SAMEORIGIN
Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Strict-Transport-Security: max-age=2592000
Server: cloudflare
CF-RAY: 6eb1692f8bd776c3-LHR
Content-Type: text/html; charset=utf-8
Expires: Thu, 01 Jan 1970 00:00:01 GMT
}}
The API documentation says:
"To authenticate against the API, include your API key in the 'Authorization' header, prefixed with 'Key ', in every request. Example: 'Authorization: Key yourapikey'"
And so, I have tried adding this to
a) the HttpClient via HttpClient.DefaultRequestHeaders.Authorization
b) the HttpClient via HttpClient.DefaultHeaders.Add
c) the HttpRequestMessage via HttpRequestMessage.Headers.Add
In each instance, the request URI looks good, as well as the headers, but still returning 403.
My current structure is:
// services
builder.Services.AddHttpClient("myplatform", c =>
{
c.BaseAddress = new Uri("https://seller-api.myplatform.com/v2/");
c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
});
// controller
// constructor uses IHttpClientFactory
this._httpClient = clientFactory.CreateClient("myplatform");
// service
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Key", platformKey);
string endPoint = "offers" + CreateQueryString(pageNumber, pageSize);
// example endPoint: offers?page_number=1&page_size=100
var requestMsg = new HttpRequestMessage()
{
Method = HttpMethod.Get,
RequestUri = new Uri(httpClient.BaseAddress + endPoint)
};
try
{
var result = await httpClient.SendAsync(requestMsg);
}
catch (Exception ex)
{
}
Again, the content of the call works when calling through GoogleAppScript. What am I doing wrong in C#, and how can I correct this?
Not sure if this is all the information needed - let me know otherwise! Important to note, the target framework is .NET 6.0.
EDIT
As suggested by a comment around duplicate clients, I have removed the client factory. I am now creating a new HttpClient in the controller constructor, and passing this client to my service to do the GET request.
this._httpClient = new HttpClient();
Again, the client and the request message look well formed at time of request but still returning 403 error. Is there an issue with my VS22 client, or web client etc.?
Also, the call I am making successfully via Google AppScript is using UrlFetchApp. Not sure what is the issue here with the C# side..
EDIT2
Adding current GAS code for reference:
var url = 'https://seller-api.platform.com/v2';
var end_point = '/offers?';
var header = {
'Authorization': api_key
}
var params = {
'method': 'GET',
'headers': header
}
// call API
var page_query = 'page_number=' + page + '&page_size=' + maxItemsPerPage;
var full_url = url + end_point + page_query;
var response = UrlFetchApp.fetch(full_url, params);
The HTTP 403 Forbidden response status code indicates that the server understands the request but refuses to authorize it.
There are two ways add request headers when using HttpClient:
Add headers for all requests using HttpClient.DefaultRequestHeaders.
HttpClient = new HttpClient();
HttpClient.DefaultRequestHeaders.Add("Key", platformKey);
var response = await HttpClient.GetAsync(GetRandomNumberUrl);
response.EnsureSuccessStatusCode();
await response.Content.ReadAsStringAsync();
Add headers per request using HttpRequestMessage.Headers.
HttpClient = new HttpClient();
using (var request = new HttpRequestMessage(HttpMethod.Get, randomNumberUrl))
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", platformKey);
var response = await HttpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
await response.Content.ReadAsStringAsync();
}
Your problem is here in this line:
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Key", platformKey);
your _httpClient and Authorization httpClient is not same instance.
Try this way:
HttpClient HttpClient = new HttpClient();
string url = "https://seller-api.platform.com/v2";
string end_point = "/offers?";
string api_key = "key here";
string page_query = "page_number=" + 10 + "&page_size=" + 20;
string full_url = url + end_point + page_query;
using (var request = new HttpRequestMessage(HttpMethod.Get, url))
{
request.Headers.Add("Authorization", api_key);
var response = await HttpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
var m = await response.Content.ReadAsStringAsync();
}
Solution 2:
Try calling it like a browser :
HttpClient httpClient = new HttpClient();
string url = "https://gatewayt.whatever.com/chkt/request/request.php";
string end_point = "/offers?";
string api_key = "key here";
string page_query = "page_number=" + 10 + "&page_size=" + 20;
string full_url = url + end_point + page_query;
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "text/html,application/xhtml+xml,application/xml");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Encoding", "gzip, deflate");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Charset", "ISO-8859-1");
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Key", api_key);
var response = await httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
await response.Content.ReadAsStringAsync();
source: Request like browser Link1 Link2 Link3
I want to send a request to a rest API and get response and show it on the form. the API documentation says that I should use my token in bearer to Authorization in the header.
I've used RestSharp nugget and this my written code:
var client = new RestClient("https://api.payping.ir");
var request = new RestRequest("v1/product/List");
request.AddHeader("Authorization", "Bearer <myToken>");
request.AddParameter("offset", 0);
request.AddParameter("limit", 10);
var response = client.Execute(request, Method.GET);
richTextBox2.Text = "Status:\n" + response.StatusCode + "\nContent:\n" + response.Content + "\nResponse:\n" + response.IsSuccessful;
but I receive an incorrect response. my final string that returns on my form by this code is:
Status:
0
Content:
Response:
False
what is my mistake? and how can I get a correct response from a rest API?
thank you for your attention
Try :
request.AddParameter("Authorization", $"Bearer {myToken}", ParameterType.HttpHeader);
Then inspect your sent packet using Fiddler to verify header is sent.
Next step is server-side then ;)
I develop a Xamarin.Android app and I need to update an audio recorded file.
For this, my client has provided me an API like this:
URL: /api/recordings/
Method: POST
Data format: multipart/form-data
Fields: some text fields and the audio file to send
When I test it on Postman, it works fine. The generate code snippets are:
POST /api/recordings/ HTTP/1.1
Host: X.X.X.X
Cache-Control: no-cache
Postman-Token: xxxxx-xxxx-xxxx-xxxx-xxxxx
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="param1"
param1 name
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="param2"
param2 name
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="audio_file"; filename="xxx.wav"
Content-Type: audio/wav
But when I try from the app, I get an 400 - Bad Request error.
First attempt:
I first tried with the following basic code:
using (HttpClient client = new HttpClient())
{
try
{
MultipartFormDataContent formData = new MultipartFormDataContent();
formData.Add(new StringContent("param1 name"), "param1");
formData.Add(new StringContent("param2 name"), "param2");
var response = await client.PostAsync(url, formData);
Logger.Log("Response : " + responseObj.ToString());
}
catch (Exception ex)
{
Logger.Log("Exception : " + ex.ToString());
}
}
But there is a 400 - Bad Request error:
Response : StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Server: nginx/1.15.0
Date: Mon, 25 Jun 2018 23:25:41 GMT
Connection: keep-alive
Vary: Cookie
X-Frame-Options: SAMEORIGIN
Content-Type: application/json
Content-Length: 85
Allow: POST, OPTIONS
}
Second attempt:
Then I've tried the following snippet that I found there:
string servResp = "";
string boundary = "----CustomBoundary" + DateTime.Now.Ticks.ToString("x");
using (var content = new MultipartFormDataContent(boundary))
{
content.Headers.Remove("Content-Type");
content.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundary=" + boundary);
content.Add(new StringContent("param1 name"), "param1");
content.Add(new StringContent("param2 name"), "param2");
HttpClientHandler handler = new HttpClientHandler();
var cookieContainer = new CookieContainer();
handler.CookieContainer = cookieContainer;
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.ExpectContinue = false;
request.Content = content;
try
{
var httpClient = new HttpClient(handler);
HttpResponseMessage response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
servResp = await response.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
Logger.Log("PostTest() - Exception : " + ex.ToString());
}
}
return servResp;
But there is still a 400 - Bad Request error:
Exception : System.Net.Http.HttpRequestException: 400 (Bad Request)
at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode () [0x0002a] in <996a681f30a44cd685a4da54e11956e2>:0
=> Would you have any explanation? How could I fix this?
Edit : the audio file
I haven't specified the code of the audio file, I use a ByteArrayContent in both cases:
byte[] b = System.IO.File.ReadAllBytes(fullFilePath);
formData.Add(new ByteArrayContent(b, 0, b.Length), "audio_file", "audio.wav");
Conclusion:
I was able to resolve my problem by creating a console project that using the same service: this allows me to find and fix my error.
For an other issue, I followed the Fiddler instructions to parameter proxy on the device. However, it seems that the proxy doesn't work for apps but only for websites in the latest versions of Android...
Do you know an alternative to Fiddler that could work on Android devices?
I am trying to a request a spotify access token using the procedure defined under 'Client Credentials Flow' on the Spotify developer page,
Here is my current implementation (Currently returns http 400 error):
using (var client = new HttpClient())
{
var requestBody = new StringContent(
"grant_type:client_credentials",
Encoding.UTF8,
"application/x-www-form-urlencoded");
var requestEncrypted = Convert.ToBase64String(
Encoding.UTF8.GetBytes(ClientId + ":" + ClientSecret));
client.DefaultRequestHeaders.Add(
"Authorization",
$"Basic {requestEncrypted}");
var tokenResult = await client.PostAsync(TokenEndpoint, requestBody);
}
I have tried other ways for formatting the request body including as json (Note: changing the encoding type to 'application/json' results in a http 415 error (media not supported)
For one, you need to use equals not a colon.
grant_type=client_credentials
Here is an example POST from the RFC.
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials