androidokhttp

How to disable SSL verification?


I tried disable SSL verification in my app, but app crashes in Android 10 in some devices. I used in my app Retrofit and Okhttp. Here how I tried to disable SSL verification in my app. I didn't find any solution from the internet.

    class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val trustAllCerts = arrayOf<TrustManager>(
            object : X509TrustManager {
                override fun checkClientTrusted(
                    chain: Array<out X509Certificate>?,
                    authType: String?
                ) {

                }

                override fun checkServerTrusted(
                    chain: Array<out X509Certificate>?,
                    authType: String?
                ) {

                }

                override fun getAcceptedIssuers(): Array<X509Certificate>? {
                    return null
                }
            }
        )

        val sslContext = SSLContext.getInstance("SSL")
        sslContext.init(null, trustAllCerts, SecureRandom())
        val sslSocketFactory = sslContext.socketFactory

        val okhttp = OkHttpClient.Builder()
            .sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
            .build()

        val retrofit = Retrofit.Builder()
            .baseUrl("https://example.com")
            .client(okhttp)
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(ScalarsConverterFactory.create())
            .build()

        val api = retrofit.create(Api::class.java)

        btn.setOnClickListener {
            api.loadMain()
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe({

                }, {
                    Log.d("myLogs", it.message)
                })
        }
    }
}

In Android 10 I catch this exception

2020-02-07 14:25:43.552 11668-11668/com.example.okhttpexample E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.okhttpexample, PID: 11668
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.okhttpexample/com.example.okhttpexample.MainActivity}: java.lang.IllegalArgumentException: Required method checkServerTrusted(X509Certificate[], String, String, String) missing
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
 Caused by: java.lang.IllegalArgumentException: Required method checkServerTrusted(X509Certificate[], String, String, String) missing
    at android.net.http.X509TrustManagerExtensions.<init>(X509TrustManagerExtensions.java:71)
    at okhttp3.internal.platform.android.Android10CertificateChainCleaner.<init>(Android10CertificateChainCleaner.kt:36)
    at okhttp3.internal.platform.Android10Platform.buildCertificateChainCleaner(Android10Platform.kt:62)
    at okhttp3.internal.tls.CertificateChainCleaner$Companion.get(CertificateChainCleaner.kt:42)
    at okhttp3.OkHttpClient$Builder.sslSocketFactory(OkHttpClient.kt:735)
    at com.example.okhttpexample.MainActivity.onCreate(MainActivity.kt:56)
    at android.app.Activity.performCreate(Activity.java:7802)
    at android.app.Activity.performCreate(Activity.java:7791)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) 
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
    at android.os.Handler.dispatchMessage(Handler.java:107) 
    at android.os.Looper.loop(Looper.java:214) 
    at android.app.ActivityThread.main(ActivityThread.java:7356) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 

This exception from crashlytics. It also happens only in Android 10

       Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.okhttpexample/com.example.okhttpexample.MainActivity}: java.lang.IllegalStateException: Unable to extract the trust manager on a, sslSocketFactory is class com.android.org.conscrypt.OpenSSLSocketFactoryImpl
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3448)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595)
   at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
   at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
   at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2147)
   at android.os.Handler.dispatchMessage(Handler.java:107)
   at android.os.Looper.loop(Looper.java:237)
   at android.app.ActivityThread.main(ActivityThread.java:7811)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)


   Caused by java.lang.IllegalStateException: Unable to extract the trust manager on a, sslSocketFactory is class com.android.org.conscrypt.OpenSSLSocketFactoryImpl
   at okhttp3.internal.platform.Platform.buildCertificateChainCleaner(Platform.java:151)
   at okhttp3.OkHttpClient$Builder.sslSocketFactory(OkHttpClient.java:698)
   at com.example.okhttpexample.di.NetworkModule.provideOkHttpClient(NetworkModule.java:277)
   at com.example.okhttpexample.di.NetworkModule_ProvideOkHttpClientFactory.provideOkHttpClient(NetworkModule_ProvideOkHttpClientFactory.java:47)
   at com.example.okhttpexample.di.NetworkModule_ProvideOkHttpClientFactory.get(NetworkModule_ProvideOkHttpClientFactory.java:36)
   at com.example.okhttpexample.di.NetworkModule_ProvideOkHttpClientFactory.get(NetworkModule_ProvideOkHttpClientFactory.java:12)
   at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
   at com.example.okhttpexample.di.NetworkModule_ProvideRetrofitFactory.get(NetworkModule_ProvideRetrofitFactory.java:32)
   at com.example.okhttpexample.di.NetworkModule_ProvideRetrofitFactory.get(NetworkModule_ProvideRetrofitFactory.java:11)
   at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
   at com.example.okhttpexample.di.NetworkModule_ProvideVeonApiFactory.get(NetworkModule_ProvideVeonApiFactory.java:27)
   at com.example.okhttpexample.di.NetworkModule_ProvideVeonApiFactory.get(NetworkModule_ProvideVeonApiFactory.java:10)
   at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
   at com.example.okhttpexample.api.NetworkHelper_Factory.get(NetworkHelper_Factory.java:42)
   at com.example.okhttpexample.api.NetworkHelper_Factory.get(NetworkHelper_Factory.java:9)
   at com.example.okhttpexample.data.repository.DataRepository_Factory.get(DataRepository_Factory.java:36)
   at com.example.okhttpexample.data.repository.DataRepository_Factory.get(DataRepository_Factory.java:10)
   at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
   at com.example.okhttpexample.di.DaggerApplicationComponent.injectMainActivity(DaggerApplicationComponent.java:600)
   at com.example.okhttpexample.di.DaggerApplicationComponent.inject(DaggerApplicationComponent.java:526)
   at com.example.okhttpexample.MainActivity.onCreate(MainActivity.java:75)
   at android.app.Activity.performCreate(Activity.java:7955)
   at android.app.Activity.performCreate(Activity.java:7944)
   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3423)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595)
   at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
   at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
   at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2147)
   at android.os.Handler.dispatchMessage(Handler.java:107)
   at android.os.Looper.loop(Looper.java:237)
   at android.app.ActivityThread.main(ActivityThread.java:7811)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)

Solution

  • Update 1:

    Ensure you are using okhttp with version 4.3.1 or above.

    You need to add the following to the proguard file inorder to avoid crash on Android 10.

    -keepclassmembers class * implements javax.net.ssl.SSLSocketFactory {
        private final javax.net.ssl.SSLSocketFactory delegate;
    }
    

    Please note that in my SocketFactory class, I had the following field:

    private final SSLSocketFactory delegate;
    

    So adjust the ProGuard rule accordingly. E.g, the access modifiers like private, final, etc. as well as the field name (delegate) should match exactly as written in the class file.


    You need to add the following to the Application tag in your manifest file to make it work with latest android versions.

    android:usesCleartextTraffic="true"
    

    Create a trust manager that does not validate certificate chains

            final TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        }
    
                        @Override
                        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        }
    
                        @Override
                        public X509Certificate[] getAcceptedIssuers() {
                            return new X509Certificate[]{};
                        }
                    }
            };
    

    Install the all-trusting trust manager

     final SSLContext sslContext = SSLContext.getInstance("SSL");
     sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
    

    Create an ssl socket factory with our all-trusting manager

    final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
    

    Register the sslSocketFactory with OkHttpClient builder

    OkHttpClient.Builder builder = new OkHttpClient.Builder();
    
    builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
    builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
    

    That's all.