OkHttp 3.13 on Android with custom trust manager fails with AssertionError
See original GitHub issueTL;DR: How to use custom trust managers with OkHttp 3.13?
We have an app that uses a custom X509TrustManager
(X509ExtendedTrustManager
on API >= 24) to implement additional certificate whitelisting requirements. Basically the custom trust manager takes system trust manager as a delegate and adds custom whitelist checks on top.
This used to work fine up to OkHttp 3.12.1.
On OkHttp 3.13.0 this fails when initialising OkHttpClient.Builder#sslSocketFactory
like:
X509TrustManager trustManager;
SSLSocketFactory sslSocketFactory;
try {
trustManager = buildTrustManager(...);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { trustManager }, null);
sslSocketFactory = sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
throw new RuntimeException(e);
}
okClientBuilder.sslSocketFactory(sslSocketFactory, trustManager);
with stacktrace like:
java.lang.AssertionError: java.lang.reflect.InvocationTargetException
at okhttp3.internal.platform.AndroidPlatform.buildCertificateChainCleaner(AndroidPlatform.java:201)
at okhttp3.internal.tls.CertificateChainCleaner.get(CertificateChainCleaner.java:41)
at okhttp3.OkHttpClient$Builder.sslSocketFactory(OkHttpClient.java:821)
...
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at okhttp3.internal.platform.AndroidPlatform.buildCertificateChainCleaner(AndroidPlatform.java:196)
at okhttp3.internal.tls.CertificateChainCleaner.get(CertificateChainCleaner.java:41)
at okhttp3.OkHttpClient$Builder.sslSocketFactory(OkHttpClient.java:821)
...
Caused by: java.lang.IllegalArgumentException: Required method checkServerTrusted(X509Certificate[], String, String, String) missing
at android.net.http.X509TrustManagerExtensions.<init>(X509TrustManagerExtensions.java:72)
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at okhttp3.internal.platform.AndroidPlatform.buildCertificateChainCleaner(AndroidPlatform.java:196)
at okhttp3.internal.tls.CertificateChainCleaner.get(CertificateChainCleaner.java:41)
at okhttp3.OkHttpClient$Builder.sslSocketFactory(OkHttpClient.java:821)
From the commits I see https://github.com/square/okhttp/commit/bdc7681b3ba16ae311d2dd21160d61315e8942ca introduced this AssertionError
while earlier execution would fall back to super
implementation.
On API >= 24 (tested only on 28) I can get rid of this crash by adding the method looked up reflectively to our X509ExtendedTrustManager
implementation:
/** This is used reflectively by Android X509TrustManagerExtensions and okhttp CertificateChainCleaner **/
@SuppressWarnings("unused")
public void checkServerTrusted(X509Certificate[] chain, String authType, String host) throws CertificateException {
// TODO figure out if something could be done with the host param
delegate.checkServerTrusted(chain, authType);
whitelistChecker.checkCertWhitelisted(chain[0]);
}
However this does not work on API < 24 (our min SDK is 21). Adding the same method to X509TrustManager
(javax.net.ssl.X509TrustManager
) just introduces another issue. This one on API 21 emulator:
Caused by: java.lang.IllegalArgumentException: tm is an instance of ...WhitelistingTrustManager which is not a supported type of X509TrustManager
at android.net.http.X509TrustManagerExtensions.<init>(X509TrustManagerExtensions.java:51)
at java.lang.reflect.Constructor.newInstance(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
at okhttp3.internal.platform.AndroidPlatform.buildCertificateChainCleaner(AndroidPlatform.java:196)
at okhttp3.internal.tls.CertificateChainCleaner.get(CertificateChainCleaner.java:41)
at okhttp3.OkHttpClient$Builder.sslSocketFactory(OkHttpClient.java:821)
Looking up the platform source the code just allows TrustManagerImpl
s which is a platform-internal class and cannot really be used in app code.
Questions:
- How would one use custom
X509TrustManager
s with OkHttp 3.13 without crashes? - Any alternative ideas for implementing custom certificate checks?
Issue Analytics
- State:
- Created 5 years ago
- Comments:8 (5 by maintainers)
Top GitHub Comments
Verified with 3.13.1. No more crashes; connectivity-related tests passing.
@dj-4war paste a stacktrace in a new issue please.