free geoip
45

Fix SSLHandshakeException in Kotlin (Complete Guide)

If you’re developing Android apps using Kotlin and suddenly encounter an SSLHandshakeException, it usually indicates a failure during the SSL/TLS…

If you’re developing Android apps using Kotlin and suddenly encounter an SSLHandshakeException, it usually indicates a failure during the SSL/TLS handshake process. This problem may be caused by outdated certificates, missing trust anchors, or incompatible TLS protocols. Let’s break down how to diagnose and fix this error step-by-step in your Kotlin-based Android project.

Fix SSLHandshakeException in Kotlin

What Is SSLHandshakeException?

SSLHandshakeException is a subclass of IOException that occurs when the SSL handshake process fails. This can happen when the server’s certificate is not trusted, has expired, or your client doesn’t support the correct version of TLS.

Common Causes

  • The server uses a certificate not recognized by the Android system.
  • You’re targeting an Android version that has stricter SSL checks (API 24+).
  • Incompatible TLS protocol (e.g., TLSv1.0 disabled).
  • Expired or self-signed SSL certificates.

Solution 1: Trust Custom SSL Certificates (Not Recommended for Production)

Use OkHttpClient with a custom TrustManager to trust all certificates. Use this only for debugging or development.

// UnsafeOkHttpClient.kt
object UnsafeOkHttpClient {
    fun getUnsafeOkHttpClient(): OkHttpClient {
        val trustAllCerts = arrayOf<TrustManager>(
            object : X509TrustManager {
                override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}
                override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {}
                override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
            }
        )

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

        val sslSocketFactory = sslContext.socketFactory

        return OkHttpClient.Builder()
            .sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
            .hostnameVerifier { _, _ -> true }
            .build()
    }
}
// UnsafeOkHttpClient.kt
object UnsafeOkHttpClient {
    fun getUnsafeOkHttpClient(): OkHttpClient {
        val trustAllCerts = arrayOf<TrustManager>(
            object : X509TrustManager {
                override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}
                override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {}
                override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
            }
        )

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

        val sslSocketFactory = sslContext.socketFactory

        return OkHttpClient.Builder()
            .sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
            .hostnameVerifier { _, _ -> true }
            .build()
    }
}

Usage in your API service:

// ApiService.kt
val client = UnsafeOkHttpClient.getUnsafeOkHttpClient()

val retrofit = Retrofit.Builder()
    .baseUrl("https://your-api.com")
    .client(client)
    .addConverterFactory(GsonConverterFactory.create())
    .build()

Solution 2: Update Security Provider (Recommended)

If your app runs on an old Android device, updating the security provider can help:

ProviderInstaller.installIfNeeded(applicationContext)

Add Google Play Services dependency:

implementation 'com.google.android.gms:play-services-base:18.2.0'

More about Google’s ProviderInstaller official documentation.

Solution 3: Enable TLS 1.2 for API < 21

For Android 4.4 (API 19), TLS 1.2 is supported but not enabled by default:

fun enableTLS12(client: OkHttpClient.Builder): OkHttpClient.Builder {
    if (Build.VERSION.SDK_INT in 16..21) {
        try {
            val sc = SSLContext.getInstance("TLSv1.2")
            sc.init(null, null, null)
            client.sslSocketFactory(Tls12SocketFactory(sc.socketFactory), systemDefaultTrustManager())
        } catch (e: Exception) {
            Log.e("TLS Error", "Error while setting TLS 1.2", e)
        }
    }
    return client
}

Use this on Retrofit client initialization.

Best Practices

  • Always use trusted CA certificates.
  • Avoid bypassing SSL verification in production.
  • Monitor certificate expiry dates.
  • Keep dependencies like OkHttp and Retrofit updated.

rysasahrial

Leave a Reply

Your email address will not be published. Required fields are marked *