When working with local HTTPS servers in mobile development, you may encounter SSL handshake issues such as Javax.Net.Ssl.SSLHandshakeException
, Java.Security.Cert.CertificateException
and CertPathValidatorException: Trust anchor for certification path not found
. These errors often happen due to issues with trusting self-signed certificates or custom root certificates. This post will guide you through handling these exceptions in a .NET MAUI app using a custom DelegatingHandler
and mkcert
certificates.
Understanding the Error
The error stack trace highlights a common issue when using HTTPS in local development environments:
System.Net.Http.HttpRequestException: Connection failure
---> Javax.Net.Ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
This occurs because the Android emulator or iOS simulator does not trust the certificate used by the local server. Typically, development certificates are self-signed or issued by a local Certificate Authority (CA), like mkcert
, and are not trusted by default on mobile devices.
Solution Overview
To solve this problem, you can create a custom DelegatingHandler
that bypasses the SSL certificate validation for development purposes. This handler will specifically trust certificates generated by mkcert
for local servers.
Create the Custom Handler
Create a class LocalHttpsClientHandler
that inherits from DelegatingHandler
and sets the InnerHandler
to the appropriate platform-specific handler.
public class LocalHttpsClientHandler : DelegatingHandler
{
public LocalHttpsClientHandler()
{
#if ANDROID
InnerHandler = new AndroidMessageHandler
{
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
{
if (cert?.Issuer != null && cert.Issuer.Contains("CN=mkcert"))
{
return true;
}
return errors == System.Net.Security.SslPolicyErrors.None;
}
};
#elif IOS
InnerHandler = new NSUrlSessionHandler
{
TrustOverrideForUrl = (sender, url, trust) => url.StartsWith("https://localhost"),
};
#else
InnerHandler = new HttpClientHandler(); // Fallback handler for other platforms
#endif
}
}
Use the Custom Handler in HttpClient
public class DataService
{
public HttpClient CreateHttpClient()
{
var handler = new LocalHttpsClientHandler();
return new HttpClient(handler);
}
public async Task<string> GetDataAsync(string url)
{
using var client = CreateHttpClient();
var response = await client.GetStringAsync(url);
return response;
}
}
Handling URLs
When setting the base URL for your HTTP client in a .NET MAUI app, you need to account for differences in accessing localhost
between Android and other platforms.
Each instance of the Android emulator is isolated from your development machine network interfaces, and runs behind a virtual router. Therefore, an emulated device can’t see your development machine or other emulator instances on the network.
However, the virtual router for each emulator manages a special network space that includes pre-allocated addresses, with the 10.0.2.2
address being an alias to your host loopback interface (127.0.0.1
on your development machine).
string baseUrl = DeviceInfo.Platform == DevicePlatform.Android ?
"https://10.0.2.2:3000" : "https://localhost:3000";
Example usage
public class DataService
{
private readonly HttpClient _httpClient;
public DataService()
{
var handler = new LocalHttpsClientHandler();
_httpClient = new HttpClient(handler)
{
BaseAddress = new Uri(DeviceInfo.Platform == DevicePlatform.Android ?
"https://10.0.2.2:3000" : "https://localhost:3000")
};
}
public async Task<string> FetchDataAsync(string endpoint)
{
var response = await _httpClient.GetStringAsync(endpoint);
return response;
}
}
Additional Resources
- mkcert GitHub Repository
- HttpClient and HttpMessageHandler in .NET
- Connect to local web services in .NET MAUI
Conclusion
Using a custom DelegatingHandler
like LocalHttpsClientHandler
in .NET MAUI can help bypass SSL handshake issues with self-signed or local development certificates, allowing you to focus on building your app without worrying about certificate trust issues.
At Aptabase, we’re developing an open-source and privacy-centric analytics platform for desktop and mobile apps. Aptabase has SDKs for various frameworks, including .NET MAUI.
If you have any questions or feedback, feel free to reach out on Twitter or join us on Discord and we’ll be happy to help!