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

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?

Related

Phoenix channels with Android client

I'm trying to create a websocket connection to my Phoenix app from an Android client. I'm trying to use this library but I'm running into this issue and I'm unable to successfully join a channel.
Upon reviewing the source code of the above java phoenix client library, it looks like the initial request from the client to connect to the socket is made with http schema and not ws (the source code explicitly changes the provided url to make sure it always uses http). It's not clear to me how this would work without additional configuration in my Phoenix app: if a socket connect request is made to http://localhost:4000/socket, the request will fail because there is no route for /socket when the schema is http.
There's nothing in the library docs that says any additional config is required in my Phoenix app to make this work, but I don't see how it could work for the reason stated above.
Does a Phoenix app have built in handling for the connection upgrade, etc, required on handshake as specified here?
As a note, I have no issues making websocket connections from my javascript web client to my Phoenix backend.
Any suggestions are appreciated!
Have you tried using the default path for a channel http://localhost:4000/socket/websocket ?

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.

Cannot send TLS 1.2 with Xamarin.Forms and VisualStudio 2017

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.

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!

com.android.volley.NoConnectionError - Android emulator with Charles Proxy

I want to proxy network traffic for an Android emulator.
I can't seem to get it to work.
My emulator is booted up using this:
emulator #Nexus_5X_API_23 -http-proxy 10.0.1.17:8888
The IP and port points to what Charles reports in the Help menu.
The SSL certificate is installed. I can open the emulator browser and Charles shows me all traffic. The browser updates as usual.
All seems good so far.
Now I attempt to run my app. My first network call goes out successfully through Charles. The response returns and Charles displays it. However the response isn't passed to the app successfully.
I've set a breakpoint in the error callback and I can see a com.android.volley.NoConnectionError which is caused by java.io.IOException: unexpected end of stream on Connection.
Why doesn't Charles pass the result back back properly to the app?
Do I need to do what's defined at the end of the configuration page on Charles?
HttpHost httpproxy = new HttpHost("192.168.0.101", 8888, "http");
httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,httpproxy);
This doesn't seem correct - what am I missing?
In order to help solving
java.io.IOException: unexpected end of stream on Connection
issue please answer the questions in the comments.
As regards to
HttpHost httpproxy = new HttpHost("192.168.0.101", 8888, "http");
httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,httpproxy);
it will not help you just like that.
In fact this is another way to apply a proxy which IMO is even better than '-http-proxy' because you can apply it anywhere not only for an emulator and it is only for this app build.
You need to apply the proxy in the Http Stack you use. for example:
public class ProxyHurlStack extends HurlStack {
#Override
protected HttpURLConnection createConnection(URL url) throws IOException {
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("10.0.1.17", 8888));
HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);
return conn;
}
}
and then for you debug build you can use smth like:
requestQueue = Volley.newRequestQueue(context, new ProxyHurlStack());
The only way to this is that install the SSL (Secure Socket Layer) certificate at server end then no need to set any Charles proxy.
Every enterprise has two development environments,
Development ( http ) : doesn't need any SSL certificate
Production ( https ) : needs SSL certificate
When production environment installs the SSL certificate then android emulator and Volley library automatically detects the network connection and your were able to consume the apis/web services as expected.
No other solution to this problem.

Categories

Resources