I'm trying to access my RESTful API to retrieve data from a MySQL database. Everything is set up and works perfectly on my C# WPF project. But when using the exact same code in Xamarin Forms (built for Android) I cannot get a successful SSL handshake with my server.
Server details
- Let's Encrypt SSL certificate (definitely valid)
- Apache BasicAuth (.htaccess)
- HTTPS only (Rewrite HTTP on), so port 443
- REST API: php-crud-api (by mevdschee) to access MariaDB 10.3
I'm using Flurl.Http (uses HttpClient) to establish the connection, but get an exception on jsonReader.Wait():
var jsonReader = "https://example.com/my_api/api.php/records/my_table?order=id,desc&size=10"
.WithHeader("Accept", "application/json")
.WithBasicAuth("username", "password")
.GetJsonAsync<JsonRootObject>();
// Wait for completion.
jsonReader.Wait();
This is my AggregateException:
System.AggregateException: One or more errors occurred. (Call failed. An error occurred while sending the request
GET https://example.com/my_api/api.php/records/my_table?order=id,desc&size=10) ---> Flurl.Http.FlurlHttpException: Call failed. An error occurred while sending the request
GET https://example.com/my_api/api.php/records/my_table?order=id,desc&size=10 ---> System.Net.Http.HttpRequestException: An error occurred while sending the request
---> System.Net.WebException: Error: TrustFailure (Authentication failed, see inner exception.) ---> System.Security.Authentication.AuthenticationException:
Authentication failed, see inner exception. ---> Mono.Btls.MonoBtlsException: Ssl error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED
at /Users/builder/jenkins/workspace/xamarin-android-d16-1/xamarin-android/external/mono/external/boringssl/ssl/handshake_client.c:1132
at Mono.Btls.MonoBtlsContext.ProcessHandshake () [0x00038] in <74989b9daab94528ac2c4b7da235b9c5>:0
at Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake (Mono.Net.Security.AsyncOperationStatus status, System.Boolean renegotiate) [0x000a1] in <74989b9daab94528ac2c4b7da235b9c5>:0
at (wrapper remoting-invoke-with-check) Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake(Mono.Net.Security.AsyncOperationStatus,bool)
at Mono.Net.Security.AsyncHandshakeRequest.Run (Mono.Net.Security.AsyncOperationStatus status) [0x00006] in <74989b9daab94528ac2c4b7da235b9c5>:0
at Mono.Net.Security.AsyncProtocolRequest.ProcessOperation (System.Threading.CancellationToken cancellationToken) [0x000ff] in <74989b9daab94528ac2c4b7da235b9c5>:0
at Mono.Net.Security.AsyncProtocolRequest.StartOperation (System.Threading.CancellationToken cancellationToken) [0x0008b] in <74989b9daab94528ac2c4b7da235b9c5>:0
What I've tried / what I know
- Code works perfectly in WPF
- Exact same code (copy-paste) does not work in Xamarin Forms (tested on Android Pie)
- does not work in emulator nor dedicated device
- accessing the REST API via browser works and delivers results as expected (tested on my PC, the emulator in Chrome and my dedicated Android)
- changing the HttpClient implementation or SSL/TLS implementation under Project properties -> Android Options -> Advanced does not help
Why is my SSL handshake failing? What is Xamarin doing differently than WPF?