not sure if I am doing this right , passing a Token value and then get some info from a webservice.
I edited this question , it is passing authentication. I will leave it for future searches.
private async void Data(string AUTH)
{
using (HttpClient client = new HttpClient())
{
var Tokens = Storage.access.AUTH;
var json = JsonConvert.SerializeObject(AUTH);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AUTH);
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
var response = client.GetAsync("https://any adrees.com").Result;
string content = response.Content.ReadAsStringAsync().Result;
if (response.IsSuccessStatusCode)
{
var content2 = await response.Content.ReadAsStringAsync();
var Items = JsonConvert.DeserializeObject<Mensajes>(content2);
}
Debug.WriteLine(content);
}
}
Not sure what type of token you are refer to, my answer will be based on OAuth access token.
You will need to create a AuthenticationHeaderValue and set it into HttpClient's headers.
var authHeader = new AuthenticationHeaderValue("bearer", Storage.accessToken.Token);
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = authHeader;
Related
I am trying to modernize some calls to Moodle REST APIs.
Everything is doing OK as long as I use querystring, but I can't pinpoint why using a PutAsync doesn't work in this case (tested with Postman, it works):
using (var httpClient = _httpClientFactory.CreateClient())
{
var url = "http://127.0.0.1/moodle/webservice/rest/server.php";
var urlFunction = UrlFunction.core_user_create_users.ToString();
var urlFormat = UrlFormat.json.ToString();
var requestModel = new GetCoursesRequestModel()
{
wstoken = [token],
wsfunction = urlFunction,
moodlewsrestformat = urlFormat
};
var jsonRequest = JsonConvert.SerializeObject(requestModel);
var stringContentRequest = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
var response = await httpClient.PutAsync(url, stringContentRequest);
response.EnsureSuccessStatusCode();
var courseDtos = await response.Content.ReadFromJsonAsync<List<MoodleAPIDtosCourseDto>>();
if (courseDtos is null)
throw new InputFormatterException(
$"Pb with response format.");
}
ยดยดยดยด
The error is generated when I try to read my response at await response.Content.ReadFromJsonAsync()
I was using OpenID and we have to switch to Xamarin.Essentials.WebAuthenticator.
I can get an authorization code from Okta using WebAuthenticator.AuthenticateAsync().
But, everything I try to then translate that code into an access token returns 400 Bad Request.
Okta's API error is "E0000021: HTTP media type not supported exception" and it goes on to say, "Bad request. Accept and/or Content-Type headers likely do not match supported values."
I have tried to follow https://developer.okta.com/blog/2020/07/31/xamarin-essentials-webauthenticator as much as possible, but we are not using the hybrid grant type like he is.
We are using only Authorization Code, which means I have to make a secondary call, and I have spent two days trying to figure out how.
private async Task LoginOktaAsync()
{
try
{
var loginUrl = new Uri(BuildAuthenticationUrl()); // that method is down below
var callbackUrl = new Uri("com.oktapreview.dev-999999:/callback"); // it's not really 999999
var authenticationResult = await Xamarin.Essentials.WebAuthenticator.AuthenticateAsync(loginUrl, callbackUrl);
string authCode;
authenticationResult.Properties.TryGetValue("code",out authCode);
// Everything works fine up to this point. I get the authorization code.
var url = $"https://dev-999999.oktapreview.com/oauth2/default/v1/token"
+"?grant_type=authorization_code"
+$"&code={authCode}&client_id={OktaConfiguration.ClientId}&code_verifier={codeVerifier}";
var request = new HttpRequestMessage(HttpMethod.Post, url);
var client = new HttpClient();
var response = await client.SendAsync(request); // this generates the 400 error.
}
catch(Exception e)
{
Debug.WriteLine($"Error: {e.Message}");
}
}
Here are the methods that produce the login url and a couple of other things:
public string BuildAuthenticationUrl()
{
var state = CreateCryptoGuid();
var nonce = CreateCryptoGuid();
CreateCodeChallenge();
var url = $"https://dev-999999.oktapreview.com/oauth2/default/v1/authorize?response_type=code"
+ "&response_mode=fragment"
+ "&scope=openid%20profile%20email"
+ "&redirect_uri=com.oktapreview.dev-999999:/callback"
+$"&client_id={OktaConfiguration.ClientId}"
+$"&state={state}"
+$"&code_challenge={codeChallenge}"
+ "&code_challenge_method=S256"
+$"&nonce={nonce}";
return url;
}
private string CreateCryptoGuid()
{
using (var generator = RandomNumberGenerator.Create())
{
var bytes = new byte[16];
generator.GetBytes(bytes);
return new Guid(bytes).ToString("N");
}
}
private string CreateCodeChallenge()
{
codeChallenge = GenerateCodeToVerify();
codeVerifier = codeChallenge;
using (var sha256 = SHA256.Create())
{
var codeChallengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeChallenge));
return Convert.ToBase64String(codeChallengeBytes);
}
}
private string GenerateCodeToVerify()
{
var str = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
Random rnd = new Random();
for (var i = 0; i < 100; i++)
{
str += possible.Substring(rnd.Next(0,possible.Length-1),1);
}
return str;
}
'''
After much online research, I discovered the issue was with how I was doing my post to get the token. This is how I made it work:
public static Dictionary<string, string> JsonDecode(string encodedString)
{
var inputs = new Dictionary<string, string>();
var json = JValue.Parse(encodedString) as JObject;
foreach (KeyValuePair<string, JToken> kv in json)
{
if (kv.Value is JValue v)
{
if (v.Type != JTokenType.String)
inputs[kv.Key] = v.ToString();
else
inputs[kv.Key] = (string)v;
}
}
return inputs;
}
private async Task<string> ExchangeAuthCodeForToken(string authCode)
{
string accessToken = string.Empty;
List<KeyValuePair<string, string>> kvdata = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("code", authCode),
new KeyValuePair<string, string>("redirect_uri", OktaConfiguration.Callback),
new KeyValuePair<string, string>("client_id", OktaConfiguration.ClientId),
new KeyValuePair<string, string>("code_verifier", codeVerifier)
};
var content = new FormUrlEncodedContent(kvdata);
var request = new HttpRequestMessage(HttpMethod.Post, OktaConfiguration.TokenUrl)
{Content = content, Method = HttpMethod.Post};
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.SendAsync(request);
string text = await response.Content.ReadAsStringAsync();
Dictionary<string, string> data = JsonDecode(text);
data.TryGetValue("access_token", out accessToken);
return accessToken;
}
I am trying to post the JSON data to Pardot. I have used the info from here to call the Pardot API and currently using Pardot form handler to post the data. I want to know if i could the data via Pardot API call by using CREATE or UPSERT instead of using a form handler.
Below is my code
class SendingDataToPardot
{
public string Login()
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
var url = "https://pi.pardot.com/api/login/version/3";
string apiKey = null;
var loginInfo = new Dictionary<string, string>
{
{"email", "xx"},
{"password", "xxx"},
{"user_key", "xxx"}
};
var httpContent = new FormUrlEncodedContent(loginInfo);
using (var client = new HttpClient())
{
HttpResponseMessage response = client.PostAsync(url, httpContent).Result;
if (response.IsSuccessStatusCode)
{
string resultValue = response.Content.ReadAsStringAsync().Result;
apiKey = XDocument.Parse(resultValue).Element("rsp").Element("api_key").Value;
return apiKey;
}
else
{
return null;
}
}
}
public string POST()
{
string Api_Key = Login();
var url = "form handler url";
var contactFormData = new Dictionary<string, string>
{
{"email", "test#test.com"},
{"FirstName", "xxx"},
{"LastName", "xxxxx"},
{"Comments", "this is a test"}
};
var data= new FormUrlEncodedContent(contactFormData);
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Api_Key);
HttpResponseMessage response = client.PostAsync(url, data).Result;
string result = response.Content.ReadAsStringAsync().Result;
return result;
}
}
}
}
For most of the APIs Pardot exposes, you need to do XML work with it.
Looks like you are using Java, so you might have luck using a public library, even if just for understanding communication patterns (we had to rewrite it for our purposes, but it did serve as a great blueprint).
Have a look at the https://github.com/Crim/pardot-java-client project and see if it helps you out.
I am following below link to integrate tableau report on web application(asp .net mvc),
https://onlinehelp.tableau.com/current/server/en-us/trusted_auth.htm
https://onlinehelp.tableau.com/current/server/en-us/trusted_auth_webrequ.htm
Code :
var uri = "http://<server ip>:8000/trusted";
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("username ", "<user>");
parameters.Add("target_site", "<site>");
var bodyParameters = new ArrayList();
foreach (var parameter in parameters)
{
bodyParameters.Add(string.Format("{0}={1}", HttpUtility.UrlEncode(parameter.Key), HttpUtility.UrlEncode(Convert.ToString(parameter.Value))));
}
string requestBody = String.Join("&", bodyParameters.ToArray());
var request = WebRequest.CreateHttp(uri);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
try
{
using (var writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(requestBody);
}
var response = (HttpWebResponse)request.GetResponse();
using (var reader = new StreamReader(response.GetResponseStream()))
{
String body = reader.ReadToEnd();
}
}
catch (Exception ex)
{
string str = ex.Message.ToString();
}
My machine is registered as trusted host on tableau server, still i am getting -1 when i request for token.
I'm trying to clear all azure storage queue message via Queue Service REST API. I've verified that the code is correct, but it still returns a 403 forbidden error. The "StorageSharedKey" and "StorageAccountName" are correct since I'm able to connect to the azure queue using those values in the connection string for the azure queue client. The storage version I'm using is "2015-12-11".
Here is the code:
internal void ClearStorageQueueMessages(string queueName)
{
const string requestMethod = "DELETE";
string urlPath = $"{queueName}/messages";
var dateInRfc1123Format = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
var canonicalizedHeaders = $"x-ms-date:{dateInRfc1123Format}\nx-ms-version:{StorageVersion}";
var canonicalizedResource = $"/{StorageAccountName}/{urlPath}";
var uri = new Uri($"https://{StorageAccountName}.queue.core.windows.net/{urlPath}");
var response = MakeDeleteRestCall(uri, requestMethod, dateInRfc1123Format, canonicalizedHeaders, canonicalizedResource);
}
internal RestResponse MakeDeleteRestCall(Uri uri, string requestMethod, string dateInRfc1123Format, string canonicalizedHeaders,
string canonicalizedResource)
{
var restResponse = new RestResponse();
var stringToSign = $"{requestMethod}\n\n\n\n\n\n\n\n\n\n\n\n{canonicalizedHeaders}\n{canonicalizedResource}";
var authorizationHeader = CreateAuthorizationHeader(stringToSign);
var request = (HttpWebRequest) WebRequest.Create(uri);
request.Method = requestMethod;
request.Headers.Add("x-ms-date", dateInRfc1123Format);
request.Headers.Add("x-ms-version", StorageVersion);
request.Headers.Add("Authorization", authorizationHeader);
//request.Accept = "application/atom+xml,application/xml";
request.Accept = "application/json";
//request.ContentType = "application/json";
using (var response = (HttpWebResponse) request.GetResponse())
{
restResponse.StatusCode = response.StatusCode;
var responseStream = response.GetResponseStream();
if (responseStream == null)
return restResponse;
using (var reader = new StreamReader(responseStream))
{
restResponse.ReturnedContent = reader.ReadToEnd();
}
}
return restResponse;
}
internal static string CreateAuthorizationHeader(string canonicalizedString)
{
string signature;
using (var hmacSha256 = new HMACSHA256(Convert.FromBase64String(StorageSharedKey)))
{
var dataToHmac = Encoding.UTF8.GetBytes(canonicalizedString);
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
var authorizationHeader = string.Format(CultureInfo.InvariantCulture, "{0} {1}:{2}", StorageSharedKey,
StorageAccountName, signature);
return authorizationHeader;
}
The problem seems to be with the header Authorization. Please check the format according to the documentation:
Authorization="[SharedKey|SharedKeyLite] :"
https://msdn.microsoft.com/en-us/library/azure/dd179428.aspx
Your function adds the shared key in plain text instead of the authorization scheme "SharedKey" or "SharedKeyLite".