By Iván Santos González and Mireia Scholz
In one of the projects we have been working on for the last months we’ve been working on both mobile development (native Android) and web development, creating a backend and a front end application. Basically, the mobile app sends messages via POST request to the backend, where they are stored, so they can be displayed in the frontend dashboard we created as well.
Android does not trust unsecure connections (HTTP instead of HTTPS) by default. We were using this kind of connections during the first stages of the project to send these messages, at least until we had a valid certificate, from the Android app to the backend. As a workaround, we enabled HTTP connections temporary the following way:
AndroidManifest.xml
|
|
This simple configuration allowed us to continue working, as we said, until we had a valid certificate in the backend and could use HTTPS. In the meantime we were still able to test the app in our local environment and in the machines that eventually were going to be used for deployment.
Once we had the certificate we redirected our network traffic to HTTPS and thought that was it. Little did we know that it wouldn’t be so easy. We were still not able to access our backend locally.
java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
Wait… what? What’s a trust anchor? Where should it be? And where are you looking for it?
We were trying to figure out what was happening for a whole week, and we are here to tell you how we managed this issue.
The first thing we did was look it up online, of course, and we came across different workarounds for this, such as enabling ALL connections or adding “patches” to the actual code that eventually will be production code, and we weren’t quite happy with any of those. We kept searching online for other solutions until we found this article deep down the Android developers documentation page.
The solution was generating our own certification authority (CA) to then generate a client certificate too. It would be necessary to add the generated CA to the Android application in order to get Android to accept this CA as a trusted CA. Moreover, we would have to add the keystore (that includes the CA certificate internally) to the backend app. Let’s see it in detail:
Importing this CA in the Android application should be done in a configuration file that must be referenced in the application manifest too.
To do this, we only have to add android:networkSecurityConfig="@xml/network_security_config in the application section of the AndroidManifest.xml. In this case, @xml/network_security_config references a configuration file that must be created inside a xml directory and whose content must be the following:
|
|
In this way, it is not necessary to install the CA certificate in every device we want to execute the application in, since it is part of the project configuration. It is worth mentioning that this configuration is inside the debug-overrides section, meaining that it is only valid when the application is executed in debug mode. This mode is the default one used by Android studio when we are in the development stage and run our applications.
As it was aforementioned, the backend application must use a keystore that contains the CA certificate and the client certificate previously signed by this CA.
To generate and sign the certificates openssl and keytool tools are needed. The next commands could be used to accomplish this:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Do you want more? We invite you to subscribe to our newsletter to get the most relevan articles.
If you enjoy reading our blog, could you imagine how much fun it would be to work with us? let's do it!
But wait a second 🖐 we've got a conflict here. Newsletters are often 💩👎👹 to us. That's why we've created the LEAN LIST, the first zen, enjoyable, rocker, and reggaetoner list of the IT industry. We've all subscribed to newsletters beyond our limits 😅 so we are serious about this.