Cannot send TLS 1.2 with Xamarin.Forms and VisualStudio 2017 - android

I am trying to send a POST transaction from Xamarin.Forms using TLS1.2 but I see them arriving to the server as TLS 1.1.
I have configured Android options:
HttpClient impletemtation as Android
SSL/TLS implementation as Native TLS 1.2+
I am implementing and executing in VisualStudio 2017, and using Android 6.0 in the emulator.
Regarding the code, I set some enviroment variables:
System.Environment.SetEnvironmentVariable("MONO_TLS_PROVIDER‌​", "btls");
System.Environment.SetEnvironmentVariable("XA_TLS_PROVIDER‌​", "btls");
System.Environment.SetEnvironmentVariable("XA_HTTP_CLIENT_HANDLER_TYPE", "Xamarin.Android.Net.AndroidClientHandler");
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Finally, POST is sent with:
using (HttpClient client = new HttpClient())
or
using (HttpClient client = new HttpClient(new NativeMessageHandler()))
or
using (HttpClient client = new HttpClient(new Xamarin.Android.Net.AndroidClientHandler()))
{
try
{
HttpResponseMessage responseHttp = await client.PostAsync(new Uri(new Uri(Constants.ApiBaseUrl), "authorize"), content);
...
Where Constants.ApiBaseUrl contains a url with https://<> format.
The problem is, when POST is sent I have no exceptions, but in my server I see with Wireshark the transaction as:
I have also tried in other way, using:
HttpWebRequest httpWebRequest = WebRequest.CreateHttp(new Uri(new Uri(Constants.ApiBaseUrl), "authorize"));
httpWebRequest.Method = "POST";
httpWebRequest.Credentials = CredentialCache.DefaultNetworkCredentials;
Stream sw = httpWebRequest.GetRequestStream();
sw.Write(contentByte, 0, contentByte.Length);
HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
With and without my own certificates using:
httpWebRequest.ClientCertificates = cryptoSvc.x509HostCertificates;
In this case, if I use
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
I get the exception
RestService-SendJsonDataAsync ERROR: Error: SecureChannelFailure
(**Ssl error:100000f0:SSL routines:OPENSSL_internal:UNSUPPORTED_PROTOCOL**
at /Users/builder/jenkins/workspace/xamarin-android/xamarin-android/external/mono/external/boringssl/ssl/handshake_client.c:808)
Without that line it is also arriving as TLS1.1.
Does anyone have any idea or suggestion about what is wrong in my case, please?
Thanks so much for your time and help.

I believe in Android 6.0, TLS 1.2 is enabled by default:
https://developer.android.com/reference/javax/net/ssl/SSLSocket.html
But, you have BTLS configuration and Native TLS 1.2, I think these are conflicting. BTLS is the Boring TLS implementation, designed to provide TLS 1.2 support on older versions of Android. I think you can safely remove those lines.
I'd first confirm what the server is allowing in terms of security and if possible have the server limit HTTPS connections to only TLS 1.2.
If you'd like to try forcing only TLS 1.2 connections on the client side, take a look at this answer (note this is in Java, but the process is the same):
How to set TLS version on apache HttpClient

I was able to work around this problem by downloading and installed VS 2022 Community - Preview. I then created a MAUI .net app and used the same code that I used in VS 2019.

Related

SignalR v2.3.0 in Android

I have a MVC .NET application that uses signalR.
I tried to download this client:
https://github.com/Gurgen/SignalR-.net-core-android-client
I ran it on my device. Pressed the connect button. But kept getting an exception.
Debugging it I found that I had to change this line
String connectionId = jsonElement.getAsJsonObject().get("connectionId").getAsString();
to this
String connectionId = jsonElement.getAsJsonObject().get("ConnectionId").getAsString();
I am already starting to feel like this client doesn't support v2.3.0 of the SignalR library in my .NET application. Any way the next exception is caused by this line:
JsonElement availableTransportsElements = jsonElement.getAsJsonObject().get("availableTransports");
I had a look at the JSON returned by SignalR and there is no such element as "availableTransports". This is what it returned
{ "Url":"/signalr/hubs/auth","ConnectionToken":"zzK0SAWXNEB1pLY2VYHWPYTMcyJIX8PnhKfLRP9fij5xbY2jDIaDyKuZQa5RvHt+KSe6h1PD9JC+RL7V2nhPzevktK781hL7ndAnZqAe3E12GawCVddFUI4R9FLDE//L","ConnectionId":"9cb5ff73-14d3-4e59-8b14-d92e47bbe948","KeepAliveTimeout":20.0,"DisconnectTimeout":30.0,"ConnectionTimeout":110.0,"TryWebSockets":false,"ProtocolVersion":"1.2","TransportConnectTimeout":5.0,"LongPollDelay":0.0 }
Ok my question, has anyone used this library? Or is there another Android library I can use that is compatible? I am new to SignalR but from what the server sent does the .NET application support websockets? I want my Android client to connect using websockets.
UPDATE
OK I have discovered that WebSocket Protocol feature was not installed in IIS. I have done that now and now this is what is returned, however the client cannot still connect to it.
{ "Url":"/signalr/hubs/auth","ConnectionToken":"6CkVnCK9KmbDemtXY/S+zCyBUdaYbaK8WmQxIw6+JxjeEzWCP7BPTiItqgvzu+hhaf6kIS4NlPln8LJLfS95UbUG4rF/8C6Y5D7eq2aKCLEU6up/c4l8YvMKheodRsKy","ConnectionId":"abe2cdca-e237-4cbd-8523-98af8c864b9b","KeepAliveTimeout":20.0,"DisconnectTimeout":30.0,"ConnectionTimeout":110.0,"TryWebSockets":true,"ProtocolVersion":"1.2","TransportConnectTimeout":5.0,"LongPollDelay":0.0}
That is a step closer as now TryWebSockets is true.

The authentication or decryption has failed error when making an SSL webservice call using Xamarin and an Android Emulator

I am developing a Xamarin mobile Android app. For data access, the app uses a Portable class library to make webservice calls to the back end. I’m using the Portable class library so that I can share it with an iOS version of the mobile app later. The data is sensitive and requires SSL for all communications which is configured in the WebAPI web service project. It uses oAuth for authentication.
The challenge I’m running into is that the initial request to authenticate is failing when I run it locally with the following error:
System.Net.Http.HttpRequestException: An error occurred while sending the request
System.Net.WebException: Error: TrustFailure (The authentication or decryption has failed.)
System.IO.IOException: The authentication or decryption has failed.
Some additional information:
I am using the following built in Visual Studio emulator and version - Android_Accelerated_x86 (Android 6.0 – API 23).
I am currently running it on localhost and following is the code snippet for this call:
HttpClient client = new HttpClient(new NativeMessageHandler())
{
BaseAddress = new Uri("https://10.0.2.2:44342/") // I also tried installing it on IIS and using port 443 on localhost. Same problem.
};
var content = new StringContent("grant_type=password&username=[USER_NAME]&password=[PASSWORD]", Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.PostAsync("Token", content).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadAsStringAsync();
var stuffList = JsonConvert.DeserializeObject<List<Stuff>>(data);
return stuffList;
}
else
{
return new List<Stuff>();
}
The call works when I test it through Fiddler on localhost, so I know that everything is configured correctly on the web service end and with authentication. But from the emulator my understanding is that I need to use IP address 10.0.2.2. I have create a self-signed cert and that hasn’t seemed to help.
I have also attempted to use Fiddler as a middleman, but I’m not seeing any activity in Fiddler when I run the app locally. I have also tried to change the network settings of the emulator, but it doesn’t appear to be having any affect. The base emulator seems to be fairly limited in these settings, but I also don’t want to pay for a more advanced one at this point in time. I have seen a number of posts with similar issues, but none of the existing recommendations that I have found are helping. Any help would be greatly appreciated!

Android nv-websocket-client with SNI

I am using android nv-websocket-client library (both 2.0 and 1.31 versions) and I am trying to open a wss: connection; however, the connection fails with 503 Service not available error message.
Upon investigating I found that HAProxy requires the clients to use the SNI extension, otherwise such error is returned regardless of the Host: header (I am using HAProxy as a loadbalancer).
Upon investigating further (with tcpdump/wireshark) I found that the client does not send SNI, a wrong certificate is returned (for a different domain), yet the client continues with the TLS connection and actually sends the HTTP request (as if no certificate checking was performed?).
My code is basically:
ws = new WebSocketFactory().createSocket(wsurl);
ws.addHeader("Authorization", "Bearer " + Config.getToken());
ws.addListener(this);
ws.connectAsynchronously();
I didn't find an easy way to set up the SSLSocketFactory, however it seems to me that the code in nv-websocket-client just uses the SSLSocketFactory.getDefault(), which should be correct? SSLCertificateSocketFactory seems to be deprecated in favour of this approach.
Am I missing some key piece about SSL setup, is this and Android bug or is this and Android 'feature'?

How to set an android app to use socket.io in ssl?

I am using a library for socket.io to make an app for android. I have managed to get the app to communicate with a nginx + node.js machine. I am now interested in using SSL for the length of the connection, but cannot seem to get it to work. I think I can figure out the nginx end, but I am having some issue with the android part. I notice that the website contained the following:
// default SSLContext for all sockets
IO.setDefaultSSLContext(mySSLContext);
IO.setDefaultHostnameVerifier(myHostnameVerifier);
// set as an option
opts = new IO.Options();
opts.sslContext = mySSLContext;
opts.hostnameVerifier = myHostnameVerifier;
socket = IO.socket("https://localhost", opts);
I only changed the http to an https, I am assuming I need to do more here, but I have no idea what the rest of this bit of code means, what are the objects mySSLContext and myHostnameVerifier and how would I generate them?

Android HTTP set proxy

I have some code that I am trying to get to work with Android API 21. It was written with a version of HTTP Client 3.x and Android uses a version of HTTP Client that is definitely 4.x but not 4.5. So I am wondering how to update this section of code specifically
if(getProxy() != null) {
client.getHostConfiguration().setProxy(getProxy().getHost(),getProxy().getPort());
if (HttpProxyCredentials.isProxySet()) {
AuthScope authScope = new AuthScope(getProxy().getHost(), getProxy().getPort());
client.getState().setProxyCredentials(authScope, new NTCredentials(HttpProxyCredentials.getUserName(),
HttpProxyCredentials.getPassword(),
"",HttpProxyCredentials.getDomain()));
Any one know how to do this Android?

Categories

Resources