Search code examples
androidxamarin.androidcertificate

Installing CA certificate on android in system context


I need to access a REST API by HTTPS from my Xamarin APP. Of course in my development environment, I don't use a publicly signed certificate but signed from my local CA. So I need to add my CA certificate to the trusted CAs on the Android emulator. After some google searches the first approach I've found was, to just drag and drop it into the emulator and then install it with the "Files" app. But this only seems to install it in the user context. Which my App doesn't seem to care about since it still did not accept the certificate from the API as trusted. So I searched for some more...

The next approach was to get the issuer hash value from the certificate, rename the file after it, disable Google APIs and Google Play Store and do this:

emulator -avd <avd_name_here> -writable-system

adb root
adb shell remount
adb push <cert_filename> /system/etc/security/cacerts
adb shell "chmod 664 /system/etc/security/cacerts/<cert_filename>"

adb reboot

This did work but has some downsides. Always launch the emulator with -writable-system which means I have to launch it manually instead of from Visual Studio, and keeping Google APIs and Google Play Store disabled. I don't know what difference it makes if I keep those APIs disabled.

I can't really believe that this is the only way to install a CA certificate. How is it done on a real device? I assume I can't just disable the google APIs there?


Solution

  • Tim Biegeleisen's comment made me invest some time looking in the direction of accessing the API in plain text. Neither Android nor iOS do allow this by default. Fortunate enough it is possible to allow it for specific domains which I think is an acceptable solution:

    Android

    Found here https://devblogs.microsoft.com/xamarin/cleartext-http-android-network-security/

    1. Add the following file and folder under resources in the Android project: xml\network_security_config.xml
    2. Add lines like this to the file:
        <?xml version="1.0" encoding="utf-8"?>
        <network-security-config>
          <domain-config cleartextTrafficPermitted="true">
            <domain includeSubdomains="true">10.0.2.2</domain> <!-- Debug port -->
            <domain includeSubdomains="true">xamarin.com</domain>
          </domain-config>
        </network-security-config>
    
    1. In Properties\AssemblyInfo.xml Add android:networkSecurityConfig to the application header:
        <manifest>
        <application android:networkSecurityConfig="@xml/network_security_config">
            ...
        </application>
        </manifest>
    

    iOS

    Found here: https://stackoverflow.com/a/33306373/3883521

    In info.plist Add Something like this:

    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>domain.com</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
        </dict>
    </dict>
    

    change domain.com to your domain...