I'm trying to login a website for parsing purpose. while program runs it seems to login to web site. I can see that from fiddler. But at the end of the program, even the status code seems tobe 200, ı find myself not logged in.
string loginUri = "https://www.sample.com";
string username = "username";
string password = "password";
CookieContainer cc = new CookieContainer();
var handler = new HttpClientHandler { CookieContainer = cc };
var request = new HttpRequestMessage(HttpMethod.Post, loginUri);
handler.AllowAutoRedirect = true;
request.Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "return_url", "emagaza.php"},
{ "user_login", "sampleuser"},
{ "password", "sapmplepass"},
{ "dispatch[auth.login]", "Giriş yap"}
});
var client = new HttpClient(handler);
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Any attempt to use cookies failed.
I tried this;
httpWebRequest2.CookieContainer = cc;
HttpWebResponse response3 = (HttpWebResponse)httpWebRequest2.GetResponse();
and I tried this;
var handler2 = new HttpClientHandler { CookieContainer = cc };
var request2 = new HttpRequestMessage(HttpMethod.Get, loginUri);
var response2 = await client.SendAsync(request2);
Related
class Program
{
public static async Task<bool> Post(string siteUrl, string requestUri, HttpContent content)
{
var credential = new System.Net.NetworkCredential(
"User",
"Pass",
"Domain");
using (var handler = new HttpClientHandler() { Credentials = credential, UseProxy = false })
{
using (var client = new HttpClient(handler))
{
client.DefaultRequestHeaders.Accept.Clear();
var mediaType = new MediaTypeWithQualityHeaderValue("application/json");
mediaType.Parameters.Add(new NameValueHeaderValue("odata", "nometadata"));
client.DefaultRequestHeaders.Accept.Add(mediaType);
client.DefaultRequestHeaders.Add("X-RequestDigest", await GetRequestDigest());
string url = string.Format(requestUri, siteUrl);
HttpResponseMessage response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
return true;
}
}
}
static async Task Main(string[] args)
{
string domain = "xxxx";
string SiteUrl = "https://SITE/";
string issuesListById = "{0}_api/web/lists/GetByTitle('issues')/items?$filter=ID eq 1";
string taskListUrlById = "{0}_api/web/lists/GetByTitle('tasks')/items?$filter=ID eq 932";
var credentials = new NetworkCredential("User", "Pass", domain);
var handler = new HttpClientHandler { Credentials = credentials };
using (var http = new HttpClient(handler))
{
var stringContent = new StringContent("", Encoding.UTF8, "application/json");
http.DefaultRequestHeaders.Accept.Clear();
http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await http.GetAsync(string.Format(taskListUrlById, SiteUrl)).ConfigureAwait(false);
string jsonData = await response.Content.ReadAsStringAsync();
var obj = JsonConvert.DeserializeObject<Tasks>(jsonData);
var itemToEdit = obj.Value.First();
itemToEdit.Status = "Close";
var content = new StringContent(JsonConvert.SerializeObject(obj), Encoding.UTF8, "application/json");
var update = await Post(SiteUrl, taskListUrlById, content);
}
}
}
I am trying to update the status of a task in a SharePoint list to "Close", I am using the post method to send the content, I am receiving "bad request" in the post method... I am using REST to communicate with SharePoint on Premise any idea on what causing this problem? (the GetRequestDigest function is working well). if someone can help... Thanks in Advance.
string taskListUrlById = "{0}_api/web/lists/GetByTitle('tasks')/items(932)"; //932 is the ID of the item to update
string SiteUrl = "yoursite";
string url = string.Format(taskListUrlById, SiteUrl);
string content = "{ '__metadata': { 'type': 'SP.Data.TasksListItem' }, 'Status': 'Close'}";
var credential = new System.Net.NetworkCredential("username",
"Password",
"domain");
using (var handler = new HttpClientHandler() { Credentials = credential, UseProxy = false })
{
using (var client = new HttpClient(handler))
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Add("X-RequestDigest", await GetRequestDigest());
request.Headers.Add("X-HTTP-Method", "MERGE");
request.Headers.Add("IF-MATCH", "*");
HttpContent strContent = new StringContent(content);
strContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
strContent.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("odata", "verbose"));
request.Content = strContent;
var response = await client.SendAsync(request);
}
}
I have a working WEB API that I wrote, and I added basic authentication to the API (username is "testing", password is "123456"). However, when trying to call that API from my web form, I keep getting the "(401) Unauthorized" message. What should I change in the web code to call the API successfully?
string url = String.Format("http://example.com"); //here I have the correct url for my API
HttpWebRequest requestObj = (HttpWebRequest)WebRequest.Create(url);
requestObj.Method = "Get";
requestObj.PreAuthenticate = true;
requestObj.Credentials = new NetworkCredential("testing", "123456");
HttpWebResponse responseObj = null;
responseObj = (HttpWebResponse)requestObj.GetResponse();
string strresult = null;
using (Stream stream = responseObj.GetResponseStream())
{
StreamReader sr = new StreamReader(stream);
strresult = sr.ReadToEnd();
sr.Close();
}
This is what my API searches for in terms of authentication:
actionContext.Request.Headers.Authorization.Parameter
Should I be adding a header instead of NetworkCredential or is it the same thing?
This should help:
HttpMessageHandler handler = new HttpClientHandler()
{
};
var httpClient = new HttpClient(handler)
{
BaseAddress = new Uri(url),
Timeout = new TimeSpan(0, 2, 0)
};
httpClient.DefaultRequestHeaders.Add("ContentType", "application/json");
//This is the key section you were missing
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes("testing:123456");
string val = System.Convert.ToBase64String(plainTextBytes);
httpClient.DefaultRequestHeaders.Add("Authorization", "Basic " + val);
HttpResponseMessage response = httpClient.GetAsync(url).Result;
string content = string.Empty;
using (StreamReader stream = new StreamReader(response.Content.ReadAsStreamAsync().Result, System.Text.Encoding.GetEncoding(_encoding)))
{
content = stream.ReadToEnd();
}
This is the line I needed:
requestObj.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes("username:password"));
I just found out that with .NET Core 3.1 you could do it like this:
HttpRequestMessage request = new HttpRequestMessage(
HttpMethod.Post,
"your-api-url-here");
request.Headers.Authorization = new BasicAuthenticationHeaderValue(username, password);
I think your API might need a header being added to it (if you haven't done so already). Take a look at this article:
https://en.wikipedia.org/wiki/Basic_access_authentication#Client_side
But essentially, your API will need an Authorization header added to it. The Authorization key will contain the word Basic followed by a space, then the username and password encrypted using Base64. So in your instance, testing:123456 would be encrypted using base64 as dGVzdGluZzoxMjM0NTY=. So the header record will look like this:
Authorization: Basic dGVzdGluZzoxMjM0NTY=
(Basic Authentication) Here is the other solution to call Authenticated API
class Program
{
static void Main(string[] args)
{
BaseClient clientbase = new BaseClient("https://website.com/api/v2/", "username", "password");
BaseResponse response = new BaseResponse();
BaseResponse response = clientbase.GetCallV2Async("Candidate").Result;
}
public async Task<BaseResponse> GetCallAsync(string endpoint)
{
try
{
HttpResponseMessage response = await client.GetAsync(endpoint + "/").ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
baseresponse.ResponseMessage = await response.Content.ReadAsStringAsync();
baseresponse.StatusCode = (int)response.StatusCode;
}
else
{
baseresponse.ResponseMessage = await response.Content.ReadAsStringAsync();
baseresponse.StatusCode = (int)response.StatusCode;
}
return baseresponse;
}
catch (Exception ex)
{
baseresponse.StatusCode = 0;
baseresponse.ResponseMessage = (ex.Message ?? ex.InnerException.ToString());
}
return baseresponse;
}
}
public class BaseResponse
{
public int StatusCode { get; set; }
public string ResponseMessage { get; set; }
}
public class BaseClient
{
readonly HttpClient client;
readonly BaseResponse baseresponse;
public BaseClient(string baseAddress, string username, string password)
{
HttpClientHandler handler = new HttpClientHandler()
{
Proxy = new WebProxy("http://127.0.0.1:8888"),
UseProxy = false,
};
client = new HttpClient(handler);
client.BaseAddress = new Uri(baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var byteArray = Encoding.ASCII.GetBytes(username + ":" + password);
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
baseresponse = new BaseResponse();
}
}
I'm write here because I was trying to send a POST request to a server api,
I tried to send also another request(the first one) and from the response it work({"success":"true", "role":"USER"}). But in the sencond request as a response I get: {"timestamp":1524589409895,"status":403,"error":"Forbidden","message":"Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-XSRF-TOKEN'.","path":"/api/v1/rec"}.
So I put all the cookies but one of them "XSRF -TOKEN" cause my program to crashSystem.Net.CookieException: The 'Name'='XSRF -TOKEN' part of the cookie is invalid
so I discovered that this cookie change every time you create a session
so I tried to get the cookies from the response of the first message and added on the header for the second one, and this is the result
I also set the NETFramework at the 4.5 version
I'm leaving a temporary account here for you so you can try this without creating an account only for a test
Request Payload from firefox
static void Main(string[] args)
{
Uri uri = new Uri("https://www.vcast.it/api/v1/rec");
cookieContainer = new CookieContainer();
cookieContainer.Add(uri, new Cookie("CONSENT", "true"));
cookieContainer.Add(uri, new Cookie("_ga", "GA1.2.940742918.1524584758"));
cookieContainer.Add(uri, new Cookie("_gid", "GA1.2.1691132054.1524584758"));
cookieContainer.Add(uri, new Cookie("remember-me", "Z1hvUnJoOHdIM3dCZ2pmYXVKamFRUT09OkpxSXUzRDVRUXd6UG14eGlVUlJMOXc9PQ"));
clienthandler = new HttpClientHandler { AllowAutoRedirect = true, UseCookies = true, CookieContainer = cookieContainer };
client = new HttpClient(clienthandler);
client.DefaultRequestHeaders.Host = "www.vcast.it";
MainAsync();
}
private static CookieContainer cookieContainer;
private static HttpClientHandler clienthandler;
private static HttpClient client;
static async void MainAsync()
{
Uri uri = new Uri("https://www.vcast.it");
var values = new Dictionary<string, string>
{
{ "username", "XXXX" },
{ "password", "XXXX" },
{ "remember-me", "undefined" },
{ "submit", "" }
};
var content = new FormUrlEncodedContent(values);
HttpResponseMessage response = await client.PostAsync("https://www.vcast.it/apiLogin?appId=58aef0c4ea5d52b2c0e4f2ed", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());
Console.WriteLine("New Cookies:");
var responseCookies = cookieContainer.GetCookies(uri).Cast<Cookie>();
foreach (var cook in responseCookies)
{
cookieContainer.Add(uri, cook);
Console.WriteLine(cook.Name + ":" + cook.Value);
}
Console.WriteLine();
clienthandler = new HttpClientHandler { UseCookies = true, CookieContainer = cookieContainer };
client = new HttpClient(clienthandler);
values = JsonConvert.DeserializeObject<Dictionary<string, string>>("{\"name\":\"Titolo registrazione\",\"fromSuggestion\":false,\"manual\":true,\"followSeries\":false,\"resolution\":\"r576\",\"format\":\"MP4\",\"defaultProvider\":\"vcloud\",\"provider\":\"vcloud\",\"channelId\":\"58138235c9e77c00018242ed\",\"startDate\":1524585300000,\"endDate\":1524588900000,\"startHour\":17,\"startMinute\":55,\"endHour\":18,\"endMinute\":55}");
content = new FormUrlEncodedContent(values);
client.DefaultRequestHeaders.Referrer = new Uri("https://www.vcast.it/manualRec/");
response = await client.PostAsync("https://www.vcast.it/api/v1/rec", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
I will gladly accept any kind of comment or answer
I have got error with RestSharp component when i am call Paypal Rest API.
I have the following code using Xamarin for Android.
public async Task<PayPalGetTokenResponse> GetAccessToken()
{
var restRequest = new RestRequest("/oauth2/token", Method.POST);
// Add headers
restRequest.AddHeader("Accept", "application/json");
restRequest.AddHeader("Accept-Language", "en_US");
// Make Authorization header
restClient.Authenticator = new HttpBasicAuthenticator(Config.ApiClientId, Config.ApiSecret);
// add data to send
restRequest.AddParameter("grant_type", "client_credentials");
var response = restClient.Execute<PayPalGetTokenResponse>(restRequest);
response.Data.DisplayError = CheckResponseStatus(response, HttpStatusCode.OK);
return response.Data;
}
But got error :"Error: SecureChannelFailure (The authentication or decryption has failed.)"
I have Also use ModernHttpClient but got same error
public async Task<PayPalGetTokenResponse> GetAccessToken()
{
string clientId = Config.ApiClientId;
string secret = Config.ApiSecret;
string oAuthCredentials = Convert.ToBase64String(Encoding.Default.GetBytes(clientId + ":" + secret));
string uriString = Config.ApiUrl+"/oauth2/token";
PayPalGetTokenResponse result;
HttpClient client = new HttpClient(new NativeMessageHandler());
var h_request = new HttpRequestMessage(HttpMethod.Post, uriString);
h_request.Headers.Authorization = new AuthenticationHeaderValue("Basic", oAuthCredentials);
h_request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
h_request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("en_US"));
h_request.Content = new StringContent("grant_type=client_credentials", UTF8Encoding.UTF8);
try
{
HttpResponseMessage response = await client.SendAsync(h_request);
//if call failed ErrorResponse created...simple class with response properties
if (!response.IsSuccessStatusCode)
{
var error = await response.Content.ReadAsStringAsync();
var errResp = JsonConvert.DeserializeObject<string>(error);
//throw new PayPalException { error_name = errResp.name, details = errResp.details, message = errResp.message };
}
var success = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<PayPalGetTokenResponse>(success);
}
catch (Exception)
{
throw new HttpRequestException("Request to PayPal Service failed.");
}
return result;
}
Have you tried to force to modern day SSL protocol?
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
This works for me:
if (ServicePointManager.SecurityProtocol != SecurityProtocolType.Tls12)
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var client = new RestClient(payPalURL) {
Encoding = Encoding.UTF8
};
var authRequest = new RestRequest("oauth2/token", Method.POST) {
RequestFormat = DataFormat.Json
};
client.Authenticator = new HttpBasicAuthenticator(clientId, secret);
authRequest.AddParameter("grant_type","client_credentials");
var authResponse = client.Execute(authRequest);
I'm coding a Xamarin cross-platform mobile app. The server is a SpringMVC server which uses JWT Tokens to authenticate against each of the endpoints/webservices. So basically when I'm doing a request to a webservice for first time, before I need to hit a /authorize POST endpoint sending my email and password, the endpoint response will contain in the "Cookie" header an authenticaton token which comes as "AUTH_TOKEN={MD5-String}". Once I got the token I send the request to the endpoint, let's say /feed. But my problem is that I cannot figure out the way of setting the "Cookie" header in the C# HttpClient. I tried everything but the endpoing just keeps responding with the login screen html instead of the actual JSON response. I tried the same steps in Postman and other REST clients and It worked. So It means that I'm doing something wrong. Here's my code:
public class RestService : IRestService
{
HttpClient client;
HttpClientHandler handler;
CookieContainer cookies;
string authToken;
public List<Feed> FeedItems { get; private set; }
public RestService()
{
cookies = new CookieContainer();
handler = new HttpClientHandler();
handler.UseCookies = true; //Otherwise It'll not use the cookies container!!
handler.CookieContainer = cookies;
client = new HttpClient(handler);
client.MaxResponseContentBufferSize = 256000;
}
public async Task<List<Role>> GetFeedDataAsync()
{
//Request credentials
//Credentials validation
var credentials = new HalliganCredential()
{
email = Constants.Username,
password = Constants.Password
};
var jsonCredentials = JsonConvert.SerializeObject(credentials);
var jsonCredentialsContent = new StringContent(jsonCredentials, Encoding.UTF8, "application/json");
var authorizeUri = new Uri(Constants.AuthorizeEndpoint);
var authorizeResponse = await client.PostAsync(authorizeUri, jsonCredentialsContent);
if (authorizeResponse.IsSuccessStatusCode)
{
//If authentication went OK
IEnumerable<Cookie> responseCookies = cookies.GetCookies(authorizeUri).Cast<Cookie>();
foreach (Cookie cookie in responseCookies)
{
if (cookie.Name.Equals("AUTH-TOKEN"))
{
authToken = cookie.Value;
}
}
}
else
{
//Authentication failed throw error
throw new HttpRequestException("Authentication failed");
}
FeedItems = new List<Feed>();
//Making the GET request
var uri = new Uri(string.Format(Constants.FeedEnpoint, string.Empty));
try
{
cookies.Add(uri, new Cookie("Cookie", string.Format("AUTH_TOKEN={0}", authToken)));
client.DefaultRequestHeaders.Add("Cookie", string.Format("AUTH_TOKEN={0}", authToken));
handler.CookieContainer.Add(uri, new Cookie("Cookie", string.Format("AUTH_TOKEN={0}", authToken)));
var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
//Credentials validation
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
FeedItems = JsonConvert.DeserializeObject<List<Feed>>(content);
}
}
catch (Exception ex)
{
Debug.WriteLine(#"ERROR {0}", ex.Message);
}
return FeedItems;
}
}
When I reach the line var content = await response.Content.ReadAsStringAsync(); the response is an HTML string instead of the actual JSON response.
I tried with several other key values for the header, although "Cookie" is the one that worked on Postman.
I tried with "Set-Cookie", "set-cookie", "Set-Cookie", setting the header as "AUTH_TOKEN". I tried all this convinations in different places like adding them in the cookie CookieContainer, in the handler CookieContainer and in the client.DefaultRequestHeaders.
I tried setting on and off the handler.UseCookies = true; //Otherwise It'll not use the cookies container!! line.
Any help will be welcome!
UPDATE
I tried with one of the suggested solutions but didn't work I tried either with UseCookies in true and false.
//Making the GET request
var baseAddress = new Uri("http://app.******.io");
using (var handler = new HttpClientHandler { UseCookies = true })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
var message = new HttpRequestMessage(HttpMethod.Get, "/api/v1/feed?api_key=sarasa");
message.Headers.Add("Cookie", string.Format("AUTH_TOKEN={0}", authToken));
message.Headers.Add("Cookie", string.Format("AUTH_TOKEN={0};", authToken));
message.Headers.Add("Set-Cookie", string.Format("AUTH_TOKEN={0}", authToken));
message.Headers.Add("AUTH_TOKEN", authToken);
var result = await client.SendAsync(message);
result.EnsureSuccessStatusCode();
if (result.IsSuccessStatusCode)
{
var content = await result.Content.ReadAsStringAsync();
FeedItems= JsonConvert.DeserializeObject<List<Feed>>(content);
}
}
return FeedItems;
UPDATE
I tried with the another solution, same results.
var baseAddress = new Uri("http://app.*****.io");
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
cookieContainer.Add(baseAddress, new Cookie("Cookie", string.Format("AUTH_TOKEN={0}", authToken)));
cookieContainer.Add(baseAddress, new Cookie("Set-Cookie", string.Format("AUTH_TOKEN={0}", authToken)));
var result = client.GetAsync("/api/v1/roles?api_key=sarasa").Result;
result.EnsureSuccessStatusCode();
if (result.IsSuccessStatusCode)
{
var content = await result.Content.ReadAsStringAsync();
RolesItems = JsonConvert.DeserializeObject<List<Role>>(content);
}
}
Is there an alternative to HttpClient?
I finally could set the Cookie header parameter, but I change HttpClient by HttpWebRequest
Getting the Cookies
//Credentials validation
var credentials = new CompanyCredential()
{
Email = Constants.Username,
Password = Constants.Password
};
var jsonCredentials = JsonConvert.SerializeObject(credentials);
var request = (HttpWebRequest) WebRequest.Create(new Uri(baseAddress, Constants.AuthorizeEndpoint));
request.ContentType = "application/json";
request.Method = "POST";
var requestStream = request.GetRequestStreamAsync().Result;
var streamWriter = new StreamWriter(requestStream);
streamWriter.Write(jsonCredentials);
streamWriter.Flush();
try
{
HttpWebResponse response = (HttpWebResponse) request.GetResponseAsync().Result;
if (response.StatusCode.Equals(HttpStatusCode.OK))
{
authToken = response.Headers["Set-Cookie"];
tokenExpireDate = DateTime.ParseExact(response.Headers["Expires"], "yyyy-MM-dd HH:mm:ss,fff",
System.Globalization.CultureInfo.InvariantCulture);
}
else
{
//Authentication failed throw error
throw new HttpRequestException("Authentication failed");
}
} catch (Exception e)
{
Debug.WriteLine(string.Format("Warning: {0}", e.Message));
}
Setting the Cookies
var request = (HttpWebRequest)WebRequest.Create(new Uri(baseAddress, endpoint));
SetHeaders(request);
if (string.IsNullOrEmpty(authToken))
{
throw new AuthTokenNullException();
}
request.Headers["Cookie"] = authToken;
request.Method = "GET";
HttpWebResponse response = request.GetResponseAsync().Result as HttpWebResponse;
if (!response.StatusCode.Equals(HttpStatusCode.OK))
{
throw new HttpRequestException(string.Format("Warning expected response as 200 and got {0}", Convert.ToString(response.StatusCode)));
}
var reader = new StreamReader(response.GetResponseStream());
string stringResponse = reader.ReadToEnd();
return JsonConvert.DeserializeObject<T>(stringResponse);