Adding a ClientCertificate in Mono - ssl

I'm trying to make a HttpRequest in Xamarin (running Mono), but I think that ClientCertificates are not implemented in Mono. If I try to implement this, I get a NotImplementedException thrown.
var handler = new NativeMessageHandler();
handler.ClientCertificates.Add(certificate); //This line throws an exception
var httpClient = new HttpClient(handler);
I'm using the NativeMessageHandler from this library.
Is there anyone that knows a workaround to this? The webapi I'm trying to communicate with requires me to use this. Any help is appreciated.

Related

HttpRequestMessage.Content is null in receiving Controller action

I've looked at some similar posts, but all had some relevant detail that does not apply in my case. I have an existing Shopper service with a Register method. It is built on .NET Framework 4.6.1 Web API. I have a number of working scenarios in which another .NET Framework 4.6.1 Web API service calls the Shopper service using HttpClient and HttpRequestMessage. I do this with GET, PUT, and POST methods and successfully pass data to the PUT and POST methods using
request.Content = new ObjectContent<MemberAddress>(memberAddress, new System.Net.Http.Formatting.JsonMediaTypeFormatter());
I'm now developing a new service, this one built on ASP.NET Core Web API. I'm attempting to call a POST action in the Shopper service. I'm getting my HttpClient from IHttpClientFactory.CreateClient. The HttpRequestMessage set up is, I think, the same as in my other calling services.
var request = new HttpRequestMessage(HttpMethod.Post, updateShopperUrl);
request.Content = new ObjectContent<MemberRegistration>(memberRegistration, new System.Net.Http.Formatting.JsonMediaTypeFormatter(), "application/json");
The call to the service looks like this:
var httpClient = _clientFactory.CreateClient();
var response = await httpClient.SendAsync(request);
I can inspect request.Content.Value before the call and it contains the object/data I expect. The controller action code on the other end looks like this:
[Route("{shopperId}/register")]
[Route("~/api/shopper/{shopperId}/register")]
[HttpPost]
public IHttpActionResult RegisterNewMember(string shopperId, [FromBody] MemberRegistration memberRegistration)
{
But the memberRegistration parameter is always null. The [FromBody] attribute is recent addition in an attempt to solve this problem, but it did not help. FromBody should be the default behavior for a complex object parameter anyway. I can POST to that endpoint with Postman and the memberRegistration data comes through.
Either I'm just missing something obvious or maybe there's something different happening in the ASP.NET Core calling side of the equation.
It appears you are trying to post JSON data
Try changing the approach a bit and see if it make a difference.
var json = JsonConvert.SerializeObject(memberRegistration);
var content = new StringContent(json, Encoding.UTF8,"application/json");
var httpClient = _clientFactory.CreateClient();
var response = await httpClient.PostAsync(updateShopperUrl, content);
The above manually serializes the object to JSON and Posts it to the web API.
It is possible there could have been an issue with the formatter used with the ObjectContent

'CspKeyContainerInfo' requires Windows Cryptographic API (CAPI), which is not available on this platform

I have upgraded my project to asp.net core v2.2 from v2.1 and everything was used to work just fine.In the code shown below, I am trying to initilaize an RSA Key for with IdentityServer4(v2.3.2) and while trying to get a token I get the following error.
try
{
var rsaProvider = new RSACryptoServiceProvider(2048);
var rsaParametersPrivate =
RsaExtensions.RsaParametersFromXmlFile(Configuration.GetSection("JwtSettings:rsaPrivateKeyXml")
.Value);
rsaProvider.ImportParameters(rsaParametersPrivate);
var securityKey = new RsaSecurityKey(rsaProvider);
_signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.RsaSha256);
_logger.LogInformation("InitializeRsaKey() successfully executed.");
}
catch (Exception ex)
{
var exception = new Exception("Identity Server RSA Key initialization failed. " + ex);
_logger.LogError(exception, "InitializeRsaKey() method failed.");
throw exception;
}
'CspKeyContainerInfo' requires Windows Cryptographic API (CAPI), which is not available on this platform. error.
Also, my project runs on a CentOS machine meanwhile I develop my project on Windows 10. So, I am aware that something existing in Windows is missing on Linux. To solve the problem any help and suggestion is appreciated.
I digged some github issues and found out that RSACryptoServiceProvider() intherits ICspAsymmetricAlgorithm and this class is supported only on Windows. For details check out here. To fix the problem I have replaced var rsaProvider = new RSACryptoServiceProvider(2048); line with var rsaProvider = RSA.Create(2048); and it works fine with .NET Core v2.2 on CentOS. Hope this helps those who have the same issue.

Replacement for PreAuthenticate in portable class libraries

I am porting a library to a PCL and have to find a solution for managing HTTP request credentials. I took away concrete credentials classes like CredentialCache (that is not portable) and is now only using ICredentials, so client applications may create proper credentials and just send an interface reference.
However one thing still needs to be resolved. On some platforms HttpWebRequest has a neat PreAuthenticate property that takes care of initial handshaking. Without it the client needs to catch and repsponds to 401 responses. But PreAuthenticate is not a part of most of PCL profiles, and I wonder if there is any resolution to that or the client will need to implement replacement logic itself (which is silly since this is a standard piece of code).
Thanks in advance
You will need to write the code to handle this yourself. An API will only be portable if it is available on all of the platforms you target. In this case PreAuthenticate was a new API in .NET 4.5 and Windows Store apps, so it won't be available in a Portable Class Library if you are targeting any other platforms (ie .NET 4, Silverlight, or Windows Phone).
I'm having the same problem. I tried to set Credentials to a single NetworkCredental(user, pass), but it doesn't work in WinRT, although it works in Windoes Phone. So far the only way to make it work in WinRT is to create the CredentialCache by reflection.
var credCacheType = Type.GetType("System.Net.CredentialCache, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
var credCache = credCacheType.GetConstructor(new Type[0]).Invoke(new object[0]);
var addMethod = credCacheType.GetMethod("Add", new Type[] { typeof(Uri), typeof(string), typeof(NetworkCredential) });
addMethod.Invoke(credCache, new object[] { new Uri(_server), "Digest", Credential });
request.Credentials = (ICredentials)credCache;
PreAuthenticate can be set using HttpClienHandler that HttpClient accepts as a parameter constructor, e.g.:
HttpClientHandler handler = new HttpClientHandler()
{
UseDefaultCredentials = true,
PreAuthenticate = true
};
HttpClient client = new HttpClient(handler);

Adding authentication to security header in WCF to consume Metro WSIT service

I use this simple way to attach username and password to the SOAP request header. This works fine inside Java boundaries, but I want to be able to call it with my WCF client. How do I do this?
I've tried the following code, but it does not include the credentials in the header:
wsClient.ClientCredentials.UserName.UserName = "Hello";
wsClient.ClientCredentials.UserName.Password = "World";
Thanks in advance!
That is quite awful non-standardized way. It uses custom HTTP Headers so you cannot expect that built in WCF mechanism will magically support such approach. How should WCF know that you want to add custom non-standard HTTP header to HTTP request (not SOAP header)?
Use this:
var proxy = new YourServiceClient();
using (var scope = new OperationContextScope(proxy.InnerChannel))
{
var prop = new HttpRequestMessageProperty();
prop.Headers.Add("UserName", "Hello");
prop.Headers.Add("Password", "World");
OperationContext context = OperationContext.Current;
context.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = prop;
proxy.CallYourOperation();
}

Mono WCF NetTcp service takes only one client at a time

While trying to build a client-server WCF application in Mono we ran into some issues.
Reducing it to just a bare example we found that the service only accepts one client at a time. If another client attempts to connect, it hangs until the first one disconnects.
Simply changing to BasicHttpBinding fixes it but we need NetTcpBinding for duplex communication. Also the problem does not appear if compiled under MS .NET.
EDIT: I doubt (and hope not) that Mono doesn't support what I'm trying to do. Mono code usually throws NotImplementedExceptions in such cases as far as I noticed. I am using Mono v2.6.4
This is how the service is opened in our basic scenario:
public static void Main (string[] args)
{
var binding = new NetTcpBinding ();
binding.Security.Mode = SecurityMode.None;
var address = new Uri ("net.tcp://localhost:8080");
var host = new ServiceHost (typeof(Hello));
host.AddServiceEndpoint (typeof(IHello), binding, address);
ServiceThrottlingBehavior behavior = new ServiceThrottlingBehavior ()
{
MaxConcurrentCalls = 100,
MaxConcurrentSessions = 100,
MaxConcurrentInstances = 100
};
host.Description.Behaviors.Add (behavior);
host.Open ();
Console.ReadLine ();
host.Close ();
}
The client channel is obtained like this:
var binding = new NetTcpBinding ();
binding.Security.Mode = SecurityMode.None;
var address = new EndpointAddress ("net.tcp://localhost:8080/");
var client = new ChannelFactory<IHello> (binding, address).CreateChannel ();
As far as I know this is a Simplex connection, isn't it?
The contract is simply:
[ServiceContract]
public interface IHello
{
[OperationContract]
string Greet (string name);
}
Service implementation has no ServiceModel tags or attributes.
I'll update with details as required.
I've played around with this a bit, and it definitely looks like a Mono bug.
I'm porting a WCF application to run in Mono at the moment. I had played with some NetTcpBinding stuff, but I hadn't tried this scenario (multiple connections to a Mono-hosted service host). However now I try it out, I'm able to reproduce - both in 2.6 and the latest daily package.
It does work in .NET, however. Any difference in behavior between Mono and .NET is classed as a bug. You should log it on Bugzilla with a test case, I would also post in the Mono newslist.
Good luck.
Definately a bug. I'm wondering if there was a version it was working correctly...
I've posted it at Novell Bugzilla, if you are interested in its progress.