cordova-plugin-advanced-http: iOS: not working with pinned cert mode

We are facing an issue with getting this plugin to work on iOS. This plugin is working fine on Android.

We are getting following error on iOS: Error: {"status":-1,"error":"cancelled"}

Some additional details about setup: We are using ionic and have also tested this plugin on starter Ionic app to make sure this is not something related to compatibility with other plugins.

We have checked relevant fixes provided for this similar issue reported in other cases but none of them have worked. e.g https://github.com/silkimen/cordova-plugin-advanced-http/issues/116#issuecomment-392517061

using package.json dependencies:

"ionic-angular": "3.9.2",
"cordova-android": "6.3.0",
"cordova-ios": "4.5.5",
"cordova-plugin-advanced-http": "^1.11.1",
ionic@3.20.0
"platforms": [
      "android",
      "ios"
    ]
npm@5.6.0
node v8.9.4
IPhone 6

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 4
  • Comments: 29 (3 by maintainers)

Most upvoted comments

@kctang Hi, Thanks. It’s working.

In my case, iOS app stopped with the log message:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'

In this context, this usually means certificate file cannot be loaded (not found or wrong format).

My issue was, I had a multiple certificate files. Only one of them was not a valid format (or somehow something is wrong with the cert):

❯ openssl x509 -in bad.cer -inform DER -text
unable to load certificate
4344235564:error:0DFFF07B:asn1 encoding routines:CRYPTO_internal:header too long:/AppleInternal/Library/BuildRoots/b6051351-c030-11ec-96e9-3e7866fcf3a1/Library/Caches/com.apple.xbs/Sources/libressl/libressl-2.8/crypto/asn1/asn1_lib.c:152:

So, in case you have multiple .cer files, please make sure EVERY .cer file is valid (even if that is not the cert that you are actively using).

Hope this helps reduce someone’s frustration when facing this issue.

module.exports = function() {

    const fs = require('fs-extra');
    const path = require('path');

    const basePathAndroid = './platforms/android/app/src/main/assets/www';
    const basePathIos = './platforms/ios/www';

    (function hasRootCertificatesFolder() {
        fs.exists('./certificates', (exists) => {
            if (!exists) throw Error('Certificates folder not found.');
            hasPlatform(basePathAndroid);
            hasPlatform(basePathIos);
        })
    })();

    function hasPlatformCertificatesFolder(basePath) {
        let basePathCertificates = path.normalize(`${basePath}/certificates`);
        fs.exists(basePathCertificates, (exists) => {
            exists ? moveCertificates(basePathCertificates) : createPlatformCertificatesFolder(basePathCertificates);
        });
    }

    function hasPlatform(platformPath) {
        fs.exists(platformPath, (exists) => {
            return exists ? hasPlatformCertificatesFolder(platformPath) : false;
        })
    }

    function createPlatformCertificatesFolder(basePath) {
        fs.mkdir(basePath, function(err) {
            return err ? err : moveCertificates(basePath); 
        })
    }

    function moveCertificates(destPath) {
        fs.copy('./certificates', destPath, function(err) {
            if (err) throw Error(`Error: ${err}`);
        })
    }

};

@elin-y the hook I was talking about, I hope it helps you. It gets the certificates folder from the root of the project and paste its content inside the www that is generated for each specific platform.