How to connect to a url using broken ssl from the windows form using httpclient - ssl

I have implemented httpClientFactory but can't connect to the backend api using broken ssl.I tried a lot and i just got the task cancelled error -> HttpClient - A task was cancelled?
I have tried to set this
public static HttpClient getHttpClient()
{
if (_httpClient == null)
{
Uri baseUri = new Uri(Url.baseUrl);
if (baseUri.Scheme == "http")
{
var handler = new HttpClientHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ServerCertificateCustomValidationCallback =
(httpRequestMessage, cert, cetChain, policyErrors) =>
{
return true;
};
_httpClient = new HttpClient(handler);
}
else
{
_httpClient = new HttpClient();
}
_httpClient.DefaultRequestHeaders.Accept.Clear();
_httpClient.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
_httpClient.BaseAddress = baseUri;
}
return _httpClient;
}

Related

HttpClient does not work with dev certifcate

I want to use HttpClient to make requests using a certificate.
I generated a dev certificate using the following command
dotnet dev-certs https -ep dev_cert.pfx -p 1234
So I created an API to use that certificate. Here is the implementation.
public static class AuthenticationExtension
{
public static void ConfigureAuthetication(this IServiceCollection services)
{
services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
var cert = new X509Certificate2(#"D:\dev_cert.pfx", "1234");
options.AllowedCertificateTypes = CertificateTypes.All;
options.ChainTrustValidationMode = X509ChainTrustMode.CustomRootTrust;
options.CustomTrustStore = new X509Certificate2Collection { cert };
options.RevocationMode = X509RevocationMode.NoCheck;
options.ValidateCertificateUse = false;
options.Events = new CertificateAuthenticationEvents
{
OnCertificateValidated = context =>
{
var validationService = context.HttpContext.RequestServices.GetService<ClientCertificateValidationService>();
if (validationService != null && validationService.ValidateCertificate(context.ClientCertificate))
{
Console.WriteLine("Success");
context.Success();
}
else
{
Console.WriteLine("invalid cert");
context.Fail("invalid cert");
}
return Task.CompletedTask;
},
OnChallenge = context =>
{
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
Console.WriteLine("Failed");
return Task.CompletedTask;
}
};
});
services.AddAuthorization();
}
}
I added the Authorize attribute in the controller method
[HttpGet(Name = "GetWeatherForecast")]
[Authorize]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
I tested the request using Postman and it worked as expected.
Then, I created a console app to make the request using HttpClient. It failed always with the Forbidden Status code.
So I tested using the obsolete WebRequest. And It worked as expected.
Here is the implementation for that
using System.Net;
using System.Security.Cryptography.X509Certificates;
var handler = new HttpClientHandler();
X509Certificate2Collection certificates = new X509Certificate2Collection();
certificates.Import(#"D:\dev_cert.pfx", "1234", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
handler.ClientCertificates.AddRange(certificates);
using var client = new HttpClient(handler);
client.BaseAddress = new Uri("https://localhost:7148/");
try
{
var response = await client.GetAsync("weatherforecast/");
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseContent);
}
else
{
Console.WriteLine($"Failed {response.StatusCode}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Failed {ex}");
}
string host = #"https://localhost:7148/weatherforecast";
try
{
ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(host);
req.AllowAutoRedirect = true;
req.ClientCertificates = certificates;
req.Method = "GET";
WebResponse resp = req.GetResponse();
Stream stream = resp.GetResponseStream();
using (StreamReader reader = new StreamReader(stream))
{
string line = reader.ReadLine();
while (line != null)
{
Console.WriteLine(line);
line = reader.ReadLine();
}
}
stream.Close();
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadLine();
My question is... Since the WebRequest is obsolete what I can do to make the HttpClient work?
Thank you in Advance!

RESTSHARP errors ( IRestResponse, Method.GET, Execute)

public virtual string GetPaymentStatus(HttpContext context, NGeniusConfiguration configuration)
{
var reference = context.Request.Query[NGeniusConstants.ApiQueryStringRef].ToString();
var token = GetAccessToken(configuration);
var url = new Uri(GetPaymentBaseUrl(configuration), string.Format(NGeniusConstants.ApiUrl.OrderStatus, configuration.OutletId, reference));
var client = new RestClient(url);
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", string.Format(NGeniusConstants.ApiauthorizationMode.Bearer, token));
request.AddHeader("accept", NGeniusConstants.ApiPaymentAcceptJson);
IRestResponse response =client.Execute(request);
if (response.StatusCode == HttpStatusCode.OK)
{
var status = JsonConvert.DeserializeObject<NGeniusOrderStatusResponse>(response.Content);
return status.Embedded.Payment.First().State;
}
else
{
throw new Exception("Error while getting the order status", response.ErrorException);
}
}
I am fairly new to .Net Core. Can someone tell me why I have errors in Method.GET, IRestResponse and Execute? I have already included "using RestSharp;" in the program as well.
for more reference the the project i am implementing is from GITHUB.

Is it possible to have Oauth in WCF Webservice?

I currently have webservice calls that create a proxy interface for a URL. I have a requirement to update the application to accept Oauth 2.0. Is it possible to use Oauth 2.0 with WCF Webservice calls?
This is my proxy interface initialization. I use it just like a regular class initialization.
var client = ServiceClient.CreateProxyInterface<MyWebServiceClass>(WebServiceUrl);
inside the proxy interface I do some authorization checks and create an instance of the requested object and return it back to the client
public static TInterface CreateProxyInterface<TInterface>(string ServiceUrl) where TInterface : class
{
var UseClientCertificate = true;
if (ServiceClient.IsUnsecuredHttpService(ServiceUrl, UseClientCertificate))
ServiceUrl = new UriBuilder(ServiceUrl)
{
Scheme = Uri.UriSchemeHttps,
Port = -1
}.Uri.ToString();
var key = TInterface.ToString() + ServiceUrl + UseClientCertificate.ToString();
ChannelFactory myChannelFactory = ServiceClient.FactoryCache[key];
proxy = ((ChannelFactory<TInterface>) mlifChannelFactory1.Factory).CreateChannel();
return proxyInterface;
}
the client can then call a method within that class
var address = client.GetAddress(personId);
On the server side, you can customize a class to inherit ServiceAuthorizationManager, and then override the CheckAccessCore method in ServiceAuthorizationManager to implement it.
Below is an example I found from previous answers:OAuth and WCF SOAP service. After my attempts, his example is effective, so I think it should help you.
public class OAuthAuthorizationManager : ServiceAuthorizationManager
{
protected override bool CheckAccessCore(OperationContext operationContext)
{
// Extract the action URI from the OperationContext. Match this against the claims
// in the AuthorizationContext.
string action = operationContext.RequestContext.RequestMessage.Headers.Action;
try
{
//get the message
var message = operationContext.RequestContext.RequestMessage;
//get the http headers
var httpHeaders = ((System.ServiceModel.Channels.HttpRequestMessageProperty)message.Properties.Values.ElementAt(message.Properties.Keys.ToList().IndexOf("httpRequest"))).Headers;
//get authorization header
var authHeader = httpHeaders.GetValues("Authorization");
if (authHeader != null)
{
var parts = authHeader[0].Split(' ');
if (parts[0] == "Bearer")
{
var tokenClaims = ValidateJwt(parts[1]);
foreach (System.Security.Claims.Claim c in tokenClaims.Where(c => c.Type == "http://www.contoso.com/claims/allowedoperation"))
{
var authorized = true;
//other claims authorization logic etc....
if(authorized)
{
return true;
}
}
}
}
return false;
}
catch (Exception)
{
throw;
}
}
private static IEnumerable<System.Security.Claims.Claim> ValidateJwt(string jwt)
{
var handler = new JwtSecurityTokenHandler();
var validationParameters = new TokenValidationParameters()
{
ValidAudience = "urn://your.audience",
IssuerSigningKey = new InMemorySymmetricSecurityKey(Convert.FromBase64String("base64encoded symmetric key")),
ValidIssuer = "urn://your.issuer",
CertificateValidator = X509CertificateValidator.None,
RequireExpirationTime = true
};
try
{
SecurityToken validatedToken;
var principal = handler.ValidateToken(jwt, validationParameters, out validatedToken);
return principal.Claims;
}
catch (Exception e)
{
return new List<System.Security.Claims.Claim>();
}
}
}

HttpClient with multiple proxies

How can one use HttpClient with a pipeline of multiple proxies?
A single proxy can be handled via HttpClientHandler:
HttpClient client1 = new HttpClient(new HttpClientHandler()
{
Proxy = new WebProxy()
{
Address = new Uri($"http://{proxyIp}:{proxyPort}"),
BypassProxyOnLocal = false,
UseDefaultCredentials = false
}
});
I want the requests to pass through multiple proxies.
I already tried subclassing DelegatingHandler like this:
public class ProxyDelegatingHandler : DelegatingHandler
{
public ProxyDelegatingHandler(string proxyIp, int proxyPort):
base(new HttpClientHandler()
{
Proxy = new WebProxy()
{
Address = new Uri($"http://{proxyIp}:{proxyPort}"),
BypassProxyOnLocal = false,
UseDefaultCredentials = false
}
})
{
}
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
return base.SendAsync(request, cancellationToken);
}
}
And passing the list to factory, but it throws an exception which is probably caused by incorrect implementation of ProxyDelegatingHandler:
var handlers = new List<DelegatingHandler>();
handlers.Add(new ProxyDelegatingHandler(ip1, port2));
handlers.Add(new ProxyDelegatingHandler(ip2, port2));
HttpClient client = HttpClientFactory.Create(handlers.ToArray())
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, url);
var res = await client.SendAsync(requestMessage);
Exception:
The 'DelegatingHandler' list is invalid because the property 'InnerHandler' of 'CustomHandler' is not null. Parametername: handlers
Related Post: link

Xamarin Android HttpClient Error when use from a Class

I have the following code that errors out when going to site what has SSL. (Error: SecureChannelFailure (The authentication or decryption has failed.) Their SSL cert is valid. When the HttpClient code is called directly there is not issue. What is wrong with my code?
Uri uri =new Uri("https://jsonplaceholder.typicode.com/posts/1");
using (HttpClient httpclient = new HttpClientClass())
{
var tt = await httpclient.GetAsync(uri);
string tx = await tt.Content.ReadAsStringAsync();
Log.Info(TAG, tx);
}
public class HttpClientClass : HttpClient
{
private HttpClient _httpclient = null;
private HttpClientHandler messagehandler = new Xamarin.Android.Net.AndroidClientHandler();
public HttpClientClass()
{
_httpclient = new HttpClient(messagehandler);
}
}
Code with No Problem
Uri uri =new Uri("https://jsonplaceholder.typicode.com/posts/1");
using (HttpClient httpclient = new HttpClient())
{
var tt = await httpclient.GetAsync(uri);
string tx = await tt.Content.ReadAsStringAsync();
Log.Info(TAG, tx);
}
Thanks to Https with TLS 1.2 in Xamarin
here is the solution. Add Nuget modernhttpclient by Paul Betts and use below. That should work within class or not.
Uri uri = new Uri("https://jsonplaceholder.typicode.com/posts/1");
using (var httpClient = new HttpClient(new NativeMessageHandler()))
{
var tt = await httpClient.GetAsync(uri);
string tx = await tt.Content.ReadAsStringAsync();
//Log.Info(TAG, tx);
}