HTTP Request with .NET Core resulting in a 403 Forbidden error - .net-core

I'm trying to make a web request to a 3rd party endpoint using .NET Core 2. The endpoint requires authentication with a client certificate and a username and password. So far everything I try results in a 403 (Forbidden) error. I've tried the following so far:
try
{
var handler = new HttpClientHandler();
handler.Credentials = new NetworkCredential(username, password);
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.SslProtocols = SslProtocols.Tls12;
handler.ClientCertificates.Add(new X509Certificate2(certificate));
var client = new HttpClient(handler);
var result = await client.GetStringAsync(url);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
I've also tried:
try
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var request = (HttpWebRequest)WebRequest.Create(url);
var cert = new X509Certificate2(certificate);
request.ClientCertificates.Add(cert);
request.Credentials = new NetworkCredential(username, password);
request.Method = "GET";
var response = (HttpWebResponse)request.GetResponse();
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
So far I'm just trying to do a GET but eventually I'll need to do a POST.
As I said above, both result in a 403. If I run the second sample against the .NET Framework it works just fine. Also, if I have Fiddler running then I get an OK status returned and not a 403.
Any thoughts on what I'm doing wrong that is preventing .NET Core from successfully connecting to an endpoint?

I ended up switching the code to what I have below and that did the trick. I set the ClientCertificateOption to be Automatic and I removed manually specifying the certificate.
try
{
var handler = new HttpClientHandler();
handler.Credentials = new NetworkCredential(username, password);
handler.ClientCertificateOptions = ClientCertificateOption.Automatic;
handler.SslProtocols = SslProtocols.Tls12;
var client = new HttpClient(handler);
var result = await client.GetStringAsync(url);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}

Related

You must provide a request body if you set ContentLength>0 or SendChunked==true. Do this by calling [Begin]GetRequestStream before [Begin]GetResponse

I tried to upload file on oracle cloud infrastructure iaas but getting the error.I am not sure whether the file that I attached in the body is in
correct format or not. ApI signing is correct and I am doubt only about
whether the code that I wrote is upto mark or not. The code snippet is mentioned below.
The code Snippet :
FileInfo f = new FileInfo(FileUpload1.FileName);
byte[] filebyte =FileUpload1.FileBytes;
var postdata = Encoding.UTF8.GetBytes(filebyte.ToString());
Console.Write(postdata.Length);
var tenancyId = ConfigurationManager.AppSettings["BMCTenancyId"];
var userId = ConfigurationManager.AppSettings["BMCUserId"];
var fingerprint = ConfigurationManager.AppSettings["BMCFingerprint"];
var privateKeyPath = ConfigurationManager.AppSettings["BMCPrivateKeyPath"];
var privateKeyPassphrase = ConfigurationManager.AppSettings["BMCPrivateKeyPassphrase"];
var signer = new RequestSigner(tenancyId, userId, fingerprint, privateKeyPath, privateKeyPassphrase);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var uri = new Uri($"https://objectstorage.us-phoenix-1.oraclecloud.com/");
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.Accept = "application/json";
request.SendChunked = true;
request.ContentType = "text/plain";
request.ContentLength =postdata.Length;
try
{
using (var stream = request.GetRequestStream())
{
stream.Write(postdata, 0, postdata.Length);
stream.Close();
}
}
catch(Exception ex)
{
Response.Write(ex.Message);
}
request.Headers["x-content-sha256"] = Convert.ToBase64String(SHA256.Create().ComputeHash(postdata));
signer.SignRequest(request);
Console.WriteLine($"Authorization header: {request.Headers["authorization"]}");
ExecuteRequest(request);
Console.WriteLine("The value of 'ContentLength' property after sending the data is {0}", request.ContentLength);
}
private static void ExecuteRequest(HttpWebRequest request)
{
try
{
var webResponse = (HttpWebResponse)request.GetResponse();
var response = new StreamReader(webResponse.GetResponseStream()).ReadToEnd();
Console.WriteLine($"Response: {response}");
}
catch (WebException e)
{
Console.WriteLine($"Exception occurred: {e.Message}");
Console.WriteLine($"Response: {new StreamReader(e.Response.GetResponseStream()).ReadToEnd()}");
}
}
For one thing, you'll need to update the URL to the following format:
var uri = new Uri($"https://objectstorage.us-phoenix-1.oraclecloud.com/n/{namespaceName}/b/{bucketName}/o/{objectName}");
Docs: https://docs.cloud.oracle.com/iaas/api/#/en/objectstorage/20160918/Object/PutObject
Also, can you please edit the question to include the complete error you are receiving, that will help with debugging.

Created a Soap Webservice and calling it in asp.net uisng code and getting error of The remote name could not be resolved

I had developed one web service in SOAP format and trying to access service in asp.net using the below mentioned code.
public static void CallWebService()
{
try
{
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var _url = "https://test.in/ModelDetail/Service.asmx";
var _action = "https://test.in/ModelDetail/GetWarrantyDetails";
XmlDocument soapEnvelopeXml = CreateSoapEnvelope();
HttpWebRequest webRequest = CreateWebRequest(_url, _action);
InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);
// begin async call to web request.
IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);
// suspend this thread until call is complete. You might want to
// do something usefull here like update your UI.
asyncResult.AsyncWaitHandle.WaitOne();
// get the response from the completed web request.
string soapResult;
//using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
using (HttpWebResponse webResponse= (HttpWebResponse)webRequest.EndGetResponse(asyncResult))
{
using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
{
soapResult = rd.ReadToEnd();
}
Console.Write(soapResult);
}
}
catch(Exception ex) { throw ex; }
}
private static HttpWebRequest CreateWebRequest(string url, string action)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Headers.Add("SOAPAction", action);
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
return webRequest;
}
private static XmlDocument CreateSoapEnvelope()
{
XmlDocument soapEnvelop = new XmlDocument();
soapEnvelop.LoadXml(#"<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:tem='https://ndb.bmw.in/'><soapenv:Header/><soapenv:Body><tem:GetWarrantyDetails><tem:IP><demono>WBA3Y37070D45</demono></tem:IP></tem:GetWarrantyDetails></soapenv:Body></soapenv:Envelope>");
return soapEnvelop;
}
private static void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest)
{
using (Stream stream = webRequest.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
}
but when i call this code i get error of The remote name could not be resolved.
Tried all method but get this error only.
What is missing or wrong i am doing?

HttpWebRequest Exception

I try to do httprequest with asp.net and C#. And I get an exception with message "The Web server refused the connection. The Web server refused the connection"
This is my code:
var webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Proxy = proxy; // Proxy's credentials have login and password
try
{
using (var response = (HttpWebResponse) webRequest.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
return reader.ReadToEnd();
}
}
}
catch (WebException e)
{
if (e.Status == WebExceptionStatus.ProtocolError)
{
WebResponse resp = e.Response;
using (var sr = new StreamReader(resp.GetResponseStream()))
{
string str = sr.ReadToEnd();
}
}
return null;
}
And in method webRequest.GetResponse() I get WebException that I read in catch block. str variable contains html-code that looks like this:
http://i.stack.imgur.com/3QIn3.png
Unfortunatelly I can not post images.
How can I fix this error?
P.S. If it is important I use Forefront TMG but I dont know whether it can affect

How to release the resource of the used HttpRequest and HttpRespone

All, Usually if we want to release the resource of something like Connection or Stream. we have to call the method like close() to make that in Asp.net.
But I don't find any method of HttpWebRequest like close() to let Asp.Net to release the resource.
So, Commonly if I want to use HttpWebRequest or HttpWebResponse , the code snippet kind like this way . Please review below. Is there anything wrong with it ? I am not sure about that . Thanks.
try
{
HttpWebRequest request = createGetHttpRequest(detailModel, RequestServiceType.GetToken,null);
string returnedContent = string.Empty;
using (var response = (HttpWebResponse)request.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(responseStream))
{
returnedContent = reader.ReadToEnd();
reader.Close();
}
}
// string statusCode = response.StatusCode.ToString();
response.Close();
}
}
catch (Exception e)
{
Log.Write(e);
}

Handle json error message from REST API through HTTPWebRepsonse

I am consuming REST API (provided by client) in C#/asp.net and manipulate json result returned by that REST API. i have consume it by following code.
HttpWebResponse res = null;
string ReturnBody = string.Empty;
string requestBody = string.Empty;
WebRequest request = WebRequest.Create(Path);
request.ContentType = "application/json";
request.Method = "POST";
request.ContentLength = json.Length;
//Add Basic Auhtentication header
string authInfo = Username + ":" + Password;
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
request.Headers["Authorization"] = "Basic " + authInfo;
System.IO.StreamWriter sw = new System.IO.StreamWriter(request.GetRequestStream());
sw.Write(json);
sw.Close();
res = (HttpWebResponse)request.GetResponse();
if (res != null)
{
using (StreamReader sr = new StreamReader(res.GetResponseStream(), true))
{
ReturnBody = sr.ReadToEnd();
StringBuilder s = new StringBuilder();
s.Append(ReturnBody);
sr.Close();
}
}
I have put above code in try catch block, so it works properly if it will return success code(200) so i can consume json response from res object as per above code
but when that REST API gives error then it will redirect to catch and res will be null so i can not access json response of error message as i can get it by Fiddler as per shown in below fig.
so help me about How can i consume that json error response through my code?
Thanks in Advance! for any help.
You will be probably getting WebException - inspect the status property. In your case, it will indicate protocol error i.e. 401/403 etc. In such case Response property can be use to get actual HTTP response. For example,
try
{
res = (HttpWebResponse)request.GetResponse();
// handle successful response
...
}
catch(WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError)
{
var response = (HttpWebResponse)ex.Response;
// use the response as needed - in your case response.StatusCode would be 403
// and body will have JSON describing the error.
..
}
else
{
// handle other errors, perhaps re-throw
throw;
}
}

Resources