I have been working on this for a day or so and have come across quite a few posts and snippets which shed some light on how to run an HTTPS server using HTTPListener in Xamarin Forms, but everything I have come across is very outdated, or targets the wrong platform, (in most cases, Windows). I am targeting Android only at the moment, though would like to do the logic for the server in the shared code, as I will eventually deploy the app to iOS as well.
My main problem has been tracking down a comprehensive guide, or even a list of the steps required. For example, on the HTTPLIstener documentation page (https://learn.microsoft.com/en-us/dotnet/api/system.net.httplistener?view=net-6.0) the text mentions needing to select a Server Certificate for the listener, or it will fail. It then goes on to describe configuring the Server Certificate using Windows-specific tools which do not have an implementation in Xamarin.
I have encountered another post which mentions putting the certificate and private key in question into a specific folder, named after the port number the listener inhabits, i.e. 55555.cer and 55555.pvk. I have tried this, using a self-signed certificate generated using the BouncyCastle library, and it will not work. The HTTP version of the server works perfectly, but the HTTPS side generates an error like:
SSL_ERROR_RX_RECORD_TOO_LONG
This is the same error I was receiving before doing anything other than adding an HTTPS prefix to the listener, so it indicates to me that nothing has changed or been affected by placing the certificate in the correct location.
Finally, I have encountered information which leads me to believe that I need to also add the self-signed certificate to the Android Trusted Certificate store, before I will be able to use it in my application. I'm about to start implementing that, but wanted to check here to see if anyone has any insight to offer that will help me along the way.
So my question is: What are the actual steps required to make HTTPListener with HTTPS support on Xamarin Forms Android work?
It's seemingly been done in the past, so presumably it will still be possible today. I'd really like to use HTTPListener versus a lower level connection API due to the convenience offered.
Follow these instructions:
Project option controls what underlying TLS library will be used by all web request, both HttpClient and WebRequest. By default, TLS 1.2 is selected:
For example:
var client = new HttpClient();
If the HttpClient implementation was set to Managed and the TLS implementation was set to Native TLS 1.2+, then the client object would automatically use the managed HttpClientHandler and TLS 1.2 for its HTTP requests.
However, if the HttpClient implementation is set to AndroidHttpClient, then all HttpClient objects will use the underlying Java class java.net.URLConnection and will be unaffected by the TLS/SSL implementation value.
Other ways to control SSL/TLS configuration
Of the three choices, the recommended approach is to use the Xamarin.Android project options to declare the default HttpMessageHandler and TLS for the entire app.
Then, if necessary, programmatically instantiate Xamarin.Android.Net.AndroidClientHandler objects declare Environment Variables
XA_HTTP_CLIENT_HANDLER_TYPE – This environment variable declares the default HttpMessageHandler that the application will use:
XA_HTTP_CLIENT_HANDLER_TYPE=Xamarin.Android.Net.AndroidClientHandler
XA_TLS_PROVIDER – This environment variable will declare which TLS library will be used, either btls, legacy, or default (which is the same as omitting this variable):
XA_TLS_PROVIDER=btls
This environment variable is set by adding an environment file to the project.
An environment file is a Unix-formatted plain-text file with a build action of AndroidEnvironment:
HttpClient Stack and SSL/TLS Implementation Selector for Android
Transport Layer Security (TLS) 1.2
App Transport Security in Xamarin.iOS
Please, see the BoringSSL implementation
I hope this helps.