How to "refresh" cookie returned with HttpClient - c#

I work on a Xamarin.Forms project where I call some WebServices that using cookies, as they was intially made for a website. There are some webservices that only return cookies, but ohers need to receive cookies for working well.
For example, the Login webservice gets a JSON and returns 2 cookies, while the Logout webservice gets an "empty" JSON, the 2 previous cookies and must return an updated value for one of these cookies.
I based on the following link to manage cookies with HttpClient:
Struggling trying to get cookie out of response with HttpClient in .net 4.5
My problem is that I can send a cookie to a webservice, I can receive the returned cookie by a webservice, but I can't receive any "updated" cookie if I've sent it before the call...
The code of the call to the Login webservice looks like this:
public async Task Login()
{
Uri uri = new Uri("http://www.website.com/Login");
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
var httpClient = new HttpClient(handler);
var jsonParam = "{\"data\":{\"device\":\"xxx\",\"login\":\"my#email.com\",\"password\":\"password\"}}";
HttpContent httpContent = new StringContent(jsonParam);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
httpClient.DefaultRequestHeaders.Add("X-HTTP-Method-Override", "PUT");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
try
{
HttpResponseMessage httpResponse = httpClient.PostAsync(uri), httpContent).Result;
//Treatment of the recovered cookies
IEnumerable<Cookie> responseCookies = cookies.GetCookies(uri).Cast<Cookie>();
foreach (Cookie cookie in responseCookies)
{
Debug.WriteLine(cookie.Name + " : " + cookie.Value);
wsCookies.Add(new KeyValuePair<string, string>(cookie.Name, cookie.Value));
}
if (httpResponse.IsSuccessStatusCode)
{
var responseText = await httpResponse.Content.ReadAsStringAsync();
}
}
catch (Exception e)
{
}
}
=> it works well: I get the expected cookies: SESSIONID=xxx and USERID=xxx
The code of my Logout method looks like this:
public async Task Logout(String test)
{
Uri uri = new Uri("http://www.website.com/Logout");
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
var httpClient = new HttpClient(handler);
var jsonParam = "{\"data\":{}}";
HttpContent httpContent = new StringContent(jsonParam);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
httpClient.DefaultRequestHeaders.Add("X-HTTP-Method-Override", "GET");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//Retrieving cookies to send
foreach (KeyValuePair<string, string> kvpCookie in wsCookies)
{
cookies.Add(uri, new Cookie(kvpCookie.Key, kvpCookie.Value));
}
try
{
HttpResponseMessage httpResponse = httpClient.PostAsync(uri, httpContent).Result;
//Treatment of the recovered cookies
IEnumerable<Cookie> responseCookies = cookies.GetCookies(uri).Cast<Cookie>();
foreach (Cookie cookie in responseCookies)
{
Debug.WriteLine(cookie.Name + " : " + cookie.Value);
wsCookies.Add(new KeyValuePair<string, string>(cookie.Name, cookie.Value));
}
if (httpResponse.IsSuccessStatusCode)
{
var responseText = await httpResponse.Content.ReadAsStringAsync();
}
}
catch (Exception e)
{
}
}
=> this method works but I don't get the expected cookies. I send the cookies (names and values) that I've received earlier (SESSIONID=xxx and USERID=xxx), but I don't get a new value for the cookies, whereas I wait USERID=deleted as I can see when I sniff it in Fiddler: I only find the 2 cookies I've sent in "responseCookies"...
=> Do you have an explanation? Is there something that I'm doing wrong? Is there another way to manage webservices and cookies?

Not sure if that is the issue, but why create the cookie container every time? You can pass the cookies along every time.
So initialize once, and then assign the existing cookie container to the requests in Login and Logout.

Related

Getting Cookie with Flurl 3.0

I need to call an endpoint to perform and retrieve 3 cookies to call another application's endpoint, and I'm using flurl 3.0 to perform the call.
The login is successful, but the cookie session is always empty. If I perform the call with Postman, I see the cookies and call the other endpoint.
This is the code I'm using:
var loginData = new
{
lt = GetLoginTicket(),
username = _enConfig.Username,
password = _enConfig.Password
};
using var session = new CookieSession(loginUrl);
{
var login = await session.Request(loginUrl).AllowAnyHttpStatus().PostUrlEncodedAsync(loginData);
_jar = login.ResponseMessage.IsSuccessStatusCode ? session.Cookies : null;
}
The documentation of the application says this:
The response code can be:
302, a redirection The authentication is successful. An SSO cookie
(also named ######) is sent in the response header.
I get the 302 Status Code and in the body, I get the correct HTML page, but the cookies are always empty.
Am I missing something?
EDIT:
I've modified the code as follows to have the Cookies. I almost solved my problem. Still, 1 cookie is missing after the post with the Url encoded body.
The code is now:
using var session = new CookieSession(_enConfig.PassportBaseEndpoint);
{
_logger.LogInformation("Getting login ticket");
var ltData = new LoginTicket();
var ltResponse = await session.Request("/login?action=get_auth_params").GetAsync();
if (ltResponse.ResponseMessage.IsSuccessStatusCode)
{
var ltString = await ltResponse.ResponseMessage.Content.ReadAsStringAsync();
ltData = JsonConvert.DeserializeObject<LoginTicket>(ltString);
if (ltData == null || string.IsNullOrEmpty(ltData.Lt))
throw new Exception("Could not deserialize login token");
}
else
throw new Exception("Could not get Login Ticket from enovia");
var loginData = new
{
lt = ltData.Lt,
username = _enConfig.Username,
password = _enConfig.Password
};
var login = await session.Request("/login/").AllowAnyHttpStatus().PostUrlEncodedAsync(loginData);
_jar = login.ResponseMessage.IsSuccessStatusCode ? session.Cookies : null;
}
After the first GET call to retrieve the login Ticket, I also get 2 cookies with a SessionID. When I perform the POST, I must also pass these cookies to have a successful login. In the response, I should get 1 more cookie with a token.
The problem now is that the login is successful, but I don't get the third cookie in the session or the login response.
EDIT 2:
Without Flurl I'm able to get the cookies with this code
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
handler.ServerCertificateCustomValidationCallback = (a, b, c, d) => true;
var client = new HttpClient(handler);
var response = client.GetAsync($"{_enConfig.PassportBaseEndpoint}/login?action=get_auth_params").Result;
var loginTicket = JsonConvert.DeserializeObject<LoginTicket>(await response.Content.ReadAsStringAsync());
var loginBody = new Dictionary<string, string>();
loginBody.Add("lt", loginTicket.Lt);
loginBody.Add("username", _enConfig.Username);
loginBody.Add("password", _enConfig.Password);
var encodedContent = new FormUrlEncodedContent(loginBody);
response = await client.PostAsync($"{_enConfig.PassportBaseEndpoint}/login", encodedContent);
_logger.LogInformation(await response.Content.ReadAsStringAsync());
Uri uri = new Uri($"{_enConfig.PassportBaseEndpoint}/login");
IEnumerable<Cookie> responseCookies = cookies.GetCookies(uri).Cast<Cookie>();
foreach (Cookie cookie in responseCookies)
Console.WriteLine(cookie.Name + ": " + cookie.Value);

C# - How do I extract a CSV file from a JSON API using HttpClient object?

My company uses a C# .net application to programmatically retrieve data from a vendor website in the form of a CSV file. However, the vendor changed their API recently to be a JSON API. I'm a bit of a novice programmer, and don't have any experience with JSON API calls. When the vendor registered my new API userID, they provided an example of how to download the necessary csv data file using curl. Here is the sample:
echo 'Going to log in to sso'
data=$(curl -c cookies.txt -X POST https://sso.theice.com/api/authenticateTfa -H "Content-Type: application/json" \
--data '{"userId":"yourApiUserId","password":"yourpassword","appKey":"yourAppKey"}')
echo 'Going to download icecleared_oil_2020_06_26.dat file from Settlement_Reports_CSV/Oil'
curl -b cookies.txt -O ' https://downloads2.theice.com/Settlement_Reports_CSV/Oil/icecleared_oil_2020_06_26.dat
Since I have no experience with Curl, I used https://curl.olsh.me/ to convert the sample above to C#. Doing so generated the following code:
//Authenticate userId (and get cookie?)
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://sso.theice.com/api/authenticateTfa"))
{
request.Content = new StringContent("{\"userId\":\"yourApiUserId\",\"password\":\"yourpassword\",\"appKey\":\"yourAppKey\"}");
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
var response = await httpClient.SendAsync(request);
}
}
//Using authentication cookie, from previous code block, retrieve dat file
var handler = new HttpClientHandler();
handler.UseCookies = false;
using (var httpClient = new HttpClient(handler))
{
using (var request = new HttpRequestMessage(new HttpMethod("GET"), "https://downloads2.theice.com/Settlement_Reports_CSV/Oil/icecleared_oil_2020_06_26.dat"))
{
request.Headers.TryAddWithoutValidation("Cookie", "cookies.txt");
var response = await httpClient.SendAsync(request);
}
}
I integrated this code into my project and was able to get it to authenticate my userID (the POST request), but cannot for the life of me figure out how to retrieve the DAT file from the second code block (the GET request). I have observed that the response from the GET request is the same no matter whether I successfully login or not with the POST request. At this point I am assuming the validation cookie from the POST request is not being picked up by the GET request, but even if it was I'd have no idea how to extract the file from the response object in the GET request.
Can anyone advise on what I need to do? Below is the code that's been integrated into my project:
public async Task DownloadAsync(List<string> iceReportFileNamesFullUrl)
{
await AuthenticateUserCredentialsOnICE();
await RetrieveIceRportFiles(iceReportFileNamesFullUrl);
}
private async Task AuthenticateUserCredentialsOnICE()
{
using (HttpClient httpClient = new HttpClient())
{
using (HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("POST"), "https://sso.theice.com/api/authenticateTfa"))
{
request.Content = new StringContent("{\"userId\":\"xxxxxxxxx\",\"password\":\"xxxxxxxxxx\",\"appKey\":\"xxxxxxxxxxx\"}");
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
HttpResponseMessage response = await httpClient.SendAsync(request);
var value = response.Content.ReadAsStringAsync();
}
}
}
private static async Task RetrieveIceRportFiles(List<string> iceReportFileNamesFullUrl)
{
foreach (string iceReportUrl in iceReportFileNamesFullUrl)
{
HttpClientHandler handler = new HttpClientHandler();
handler.UseCookies = false;
using (HttpClient httpClient = new HttpClient(handler))
{
using (HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("GET"), iceReportUrl))
{
request.Headers.TryAddWithoutValidation("Cookie", "cookies.txt");
HttpResponseMessage response = await httpClient.SendAsync(request);
var value = response.Content.ReadAsStringAsync();
}
}
}
}
-UPDATE: 25 AUG 2020-
Thanks for your comments y'all. You made it clear that I wasn't capturing the cookies from the POST request. After some research (this, this, and this), I've updated the code so that it now successfully downloads the CSV/DAT file. I've posted what I have below, though it still requires error handling, checks for failed login, etc. I'm also sure there will be critical feedback.
Here it is:
private CookieContainer authenticationCookieContainer;
//main method for downloading file
public async Task DownloadAsync(string iceReportDownloadUrl)
{
await AuthenticateUserCredentialsOnIceAsync();
await SendDownloadReportRequestAsync(iceReportDownloadUrl);
}
Authenticate the credientials via JSON API and store authentication cookies in authenticationCookieContainter
private async Task AuthenticateUserCredentialsOnIceAsync()
{
//This will contain the ICE authentication cookies
//if the login is successful
authenticationCookieContainer = new CookieContainer();
//Create and assign handler for proxy config and cookie storage
using (HttpClientHandler handler = new HttpClientHandler() { CookieContainer = authenticationCookieContainer })
{
using (HttpClient httpClient = new HttpClient(handler))
{
using (HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("POST"), "https://sso.theice.com/api/authenticateTfa"))
{
request.Content = new StringContent("{\"userId\":\"xxxxxxxxxxx\",\"password\":\"xxxxxxxxxxxxxx\",\"appKey\":\"xxxxxxxxxxxxx\"}");
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
HttpResponseMessage response = await httpClient.SendAsync(request);
}
}
}
}
If the login was successful, the authenticationCookieContainer will contain
the login cookies and allow you to request the data at the specified
url
private async Task SendDownloadReportRequestAsync(string iceReportDownloadUrl)
{
if (authenticationCookieContainer != null)
{
//Create and assign handler for proxy config and cookie storage
using (HttpClientHandler handler = new HttpClientHandler() { CookieContainer = authenticationCookieContainer })
{
//Set to true to use the cookies obtained during authentication call
handler.UseCookies = true;
using (HttpClient httpClient = new HttpClient(handler))
{
Uri iceReportUri = new Uri(iceReportDownloadUrl);
//Request the ICE data file using the url passed through
using (HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("GET"), iceReportUri.AbsoluteUri))
{
HttpResponseMessage response = await httpClient.SendAsync(request);
using (Stream responseStream = await response.Content.ReadAsStreamAsync())
{
//Write the extracted file to the file path
byte[] content = StreamToByteArray(responseStream);
File.WriteAllBytes(#"C:\Users\my.name\Desktop\" + iceReportUri.Segments.Last(), content);
}
}
}
}
}
}
private static byte[] StreamToByteArray(Stream stream)
{
using (MemoryStream memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
}

How to add Authentication token in HttpRequest in Adaptive dialog?

I am using Botframework adaptive dialog template (c#). I already obtained a token from a HttpRequest and saved it as a conversation state property conversation.token, now I am trying to use this token to make another API call with HttpRequest. But from the official document of HttpRequest Class, it seems there is no options to add the authentication token. I tried to add the token in the Headers, but did not work, it showed 401 Unauthorized error. How should the authorization be handled in HttpRequest in adaptive dialog?
new HttpRequest()
{
Url = "http://example.com/json",
ResultProperty = "conversation.httpResponse",
Method = HttpRequest.HttpMethod.GET,
ResponseType = HttpRequest.ResponseTypes.Json,
Headers = new Dictionary<string, AdaptiveExpressions.Properties.StringExpression>()
{
{"Authorization", "Bearer ${conversation.token.content.token}"},
},
},
new SendActivity("${conversation.httpResponse}"),
Instead of using HttpRequest, I made the API call inside CodeAction with custom code.
First make a POST request to get the token, then make a GET request to call the main API. In the GET request, the authorization can be added in this way: client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);.
new CodeAction(async (dc, options) =>
{
var my_jsondata = new
{
Username = "username",
Password = "password"
};
var json = JsonConvert.SerializeObject(my_jsondata);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var Tokenurl = "https://example.com/token?HTTP/1.1";
using var Tokenclient = new HttpClient();
var Tokenresponse = await Tokenclient.PostAsync(Tokenurl, data);
string Toeknresult = Tokenresponse.Content.ReadAsStringAsync().Result;
var Tokenjo = JObject.Parse(Tokenresult);
using var client = new HttpClient();
var url = "https://example.com/mainapi?HTTP/1.1";
var accessToken = Tokenjo["token"];
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
var response = await client.GetAsync(url);
string result = response.Content.ReadAsStringAsync().Result;
dc.State.SetValue("conversation.httpresponse", response);
dc.State.SetValue("conversation.result", result);
return await dc.EndDialogAsync();
}),

c# windows phone and store app post data to php with cookie

I'm working with one of user controlled application. This app is connecting with PHP files to login and do any other processes that requested.
in PHP I'm using session for detect if user already login. When they login successfully php sets and send login token id successfully.
I already working with IOS for same project and in IOS login process is working fine. IOS uses cookies automatically but I couldn't use cookies for windows app. Session has named cookie token id and php file checks token id with posted. I stuck in windows but I have no problem with IOS.
In windows store and phone app I can post perfectly and I can get respond message too. I can login perfectly as well. But when I navigate to second page of app it checks we are login or not again. When it check I'm facing with not logged in message. In my IOS app run perfectly. But in windows session token id check fails..
this is my php file that checks session token id in second page:
$tokencheck = $_POST['Tokenid'];
if($_SESSION["token"] == $tokencheck){
first page is login page and when login successfull windows phone gets token id and saves it successfully. After login, in a second page saved token id posting to php that I shared. I checked token id and thats true.
I do some research and I found problem is cookies. I can't use cookies right now. I did some more codes but still I stuck and couldn't solved this problem.
Codes sends post perfectly and also gets respond messages perfectly but I couldn't check session token id, this is because login check fails.
First page, first attempt with httpClient
var values = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("Email", txtEmail.Text),
new KeyValuePair<string, string>("Password", txtPassword.Password)
};
string url = ".../login.php";
CookieContainer Cookiejar = new CookieContainer();
var handler = new HttpClientHandler
{
CookieContainer = Cookiejar,
UseCookies = true//,
// UseDefaultCredentials = false
};
var httpClient = new HttpClient(handler);
httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
HttpResponseMessage response = await httpClient.PostAsync(url, new FormUrlEncodedContent(values));
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
var wwwUri = new Uri(url);
Cookiejar.SetCookies(wwwUri, Cookiejar.GetCookieHeader(wwwUri));
First page second attempt with HttpWebRequest
CookieContainer cookies = new CookieContainer();
HttpWebRequest getRequest = (HttpWebRequest)WebRequest.Create(url);
getRequest.CookieContainer = cookies;
getRequest.Method = "POST";
HttpWebResponse response = (HttpWebResponse)await getRequest.GetResponseAsync();
var sr = new StreamReader(response.GetResponseStream() );
string responseString = sr.ReadToEnd();
I also tried some other codes that I found in internet but can't solved yet.
Second page is also :
object lgntoken = Windows.Storage.ApplicationData.Current.LocalSettings.Values["logintokenid"];
var values = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("Tokenid", Convert.ToString(lgntoken))
};
string url = ".../get_projects_list.php";
CookieContainer Cookiejar = new CookieContainer();
var wwwUri = new Uri(url);
// Cookiejar.SetCookies(wwwUri, Cookiejar.GetCookieHeader(wwwUri));
Cookiejar.GetCookieHeader(wwwUri);
var handler = new HttpClientHandler
{
CookieContainer = Cookiejar,
UseCookies = true
};
System.Diagnostics.Debug.WriteLine("Login Token: " + Convert.ToString(lgntoken) + "..");
var httpClient = new HttpClient(handler);
HttpResponseMessage response = await httpClient.PostAsync(url, new FormUrlEncodedContent(values));
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
System.Diagnostics.Debug.WriteLine("Project List Data : " + responseString + " ++ Login Token: " + Convert.ToString(lgntoken) + "..");
I have some experiance in IOS but I'm newbie in windows store apps. I stuck about this issue and already not understood what should I do, how can I set or get cookies in a first and second page. Waiting your helps, thank you.
SOLVED !
problem is cookies resets in second page. And also need define cookies..
using cookies with httpclient :
public static CookieContainer cookies = new CookieContainer();
var handler = new HttpClientHandler
{
CookieContainer = cookies,
UseCookies = true,
UseDefaultCredentials = false
};
HttpClient htclient = new HttpClient(handler);
Full code example
First page login screen :
public static CookieContainer cookies = new CookieContainer();
private async void btnLogin_Click(object sender, RoutedEventArgs e)
{
...
var values = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("Email", txtEmail.Text),
new KeyValuePair<string, string>("Password", txtPassword.Password)
};
string url = ".../login.php";
var handler = new HttpClientHandler
{
CookieContainer = cookies,
UseCookies = true,
UseDefaultCredentials = false
};
HttpClient htclient = new HttpClient(handler);
htclient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
HttpResponseMessage response = await htclient.PostAsync(url, new FormUrlEncodedContent(values));
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
Second page should use first page cookies.. After login :
var values = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("Tokenid", Convert.ToString(lgntoken))
};
string url = ".../get_projects_list.php";
var handler = new HttpClientHandler
{
CookieContainer = MainPage.cookies,
UseDefaultCredentials = true,
UseCookies = true
};
System.Diagnostics.Debug.WriteLine("Login Token: " + Convert.ToString(lgntoken) + "..");
// var httpClient = new HttpClient(handler);
HttpClient htclient = new HttpClient(handler);
htclient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
HttpResponseMessage response = await htclient.PostAsync(url, new FormUrlEncodedContent(values));
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
System.Diagnostics.Debug.WriteLine("Project List Data : " + responseString +
" ++ Login Token: " + Convert.ToString(lgntoken) + "..");
...
}

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