How to trust all SSL certificates with KMM and Ktor

Alistair Sykes
3 min readMar 22, 2023

Warning — Trusting all certificates is dangerous. It means you cannot trust that the server is who you think it is.

Why

Often API test environments are not signed with a certificate authority backed certificate. This is to save time and avoid expiring certificates. By default, mobile applications will not allow communication with such servers.

When developing mobile applications it can be necessary to communicate with such APIs. Again I stress this can be dangerous and precautions should be taken. For example, by using isolated devices which cannot access any real data.

Project Setup

For this post, I am assuming a standard/template Kotlin Multiplatform Mobile (KMM) setup using Kotlin 1.8.0 and Ktor 2.2.3. I have a compileSdk of 33 and minSdk of 29 for Android. I have an iOS deployment target of 15.0. I am using Ktor engines OkHttp for Android and Darwin for iOS.

Here’s an example of the shared/build.gradle.ktsfor reference

Client Configuration

First, we need to configure our HttpClient. We need to enable some common configuration and then platform specific too. Here is an approach you can take to achieve that:

commonMain/kotlin/com/example/client/HttpClient.kt`

androidMain/kotlin/com/example/client/AndroidHttpClient.kt

iosMain/kotlin/com/example/client/IosHttpClient.kt

Android Trust All

For Android to trust all certificates we need to provide a custom implementation of an X509TrustManager. In this implementation, we will make every certificate check a no-op.

androidMain/kotlin/com/example/client/AllCertsTrustManager.kt

Then to use this custom trust manager:

androidMain/kotlin/com/example/client/AndroidHttpClient.kt

You will likely want to limit this configuration to only test environments. How you might do that is out of the scope of this post. But you could consider setting different base URLs for each environment. Then you can use that to determine whether this configuration should be applied.

iOS Trust All

To allow us to loosen the server trust evaluation we must first set a property in our Info.plist

iosApp/iosApp/Info.plist

You can read more about NSExceptionAllowsInsecureHTTPLoads here. Note that we must specify the domains which we wish to loosen.

Now we can write a custom implementation of a ChallengeHandler.

iosMain/kotlin/com/example/client/TrustAllChallengeHandler.kt

In this ChallengeHandler we copy the server’s certificates. We then set them as anchor certificates. This means when we evaluate the trust with the server it should pass.

Then to use this custom ChallengeHandler:

iosMain/kotlin/com/example/client/IosHttpClient.kt

Again, you will likely want to limit this configuration to only test environments.

Summary

Please take caution with this approach. Don’t use this in production.

We discussed why you might want to override the certificate trust evaluation. We explored implementing trust all certificate configurations with Ktor in a KMM project. We leveraged expect / actual to provide platform-specific configurations.

A previous post

Originally published at brightec.co.uk. For more content check out the brightec blog.

--

--

Alistair Sykes
Alistair Sykes

Responses (3)