silkimen / cordova-plugin-advanced-http

Cordova / Phonegap plugin for communicating with HTTP servers. Allows for SSL pinning!
MIT License
400 stars 321 forks source link

iOS: not working with pinned cert mode #137

Closed ravi-pandit14 closed 5 years ago

ravi-pandit14 commented 6 years ago

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
vipin1code commented 6 years ago

Is there any fix for this issue?

vipin1code commented 6 years ago

Some additional information on this issue. We have checked and verified that certificate we are using is DER encoded based on this comment and article referred to in link.

This is the code:

cordova.plugin.http.setDataSerializer('json');
cordova.plugin.http.setSSLCertMode('pinned', function () {
     cordova.plugin.http.get(url, {}, headers, function (response) {
          console.log(response.status);
     }, function (response) {
          console.log("error")
     });
      }, function () {
        console.log('error :(');
});

So encoding format of certificate is correct. But issue still persists and the error code we are getting is

error code: -999

@silkimen We have checked with latest releases pushed over past few days but none of them seems to fix this issue. Plugin works fine if default or nocheck is passed to setSSLCertMode function but on passing pinned it throws above error.

We would really appreciate any help or input on this issue. Please let me know if you need any more details to replicate this issue.

Thanks

silkimen commented 6 years ago

Hi Vipin, is your endpoint publicly available, so I can test it on my device?

vipin1code commented 6 years ago

@silkimen Thanks for responding. It isn't available publically. That is why I haven't been able to upload a demo version of this project so far which only contains only this plugin on ionic starter project. Also I am directly using cordova instead of ionic native to rule out any issues related to that.

I am not sure how to make it easier for you to debug this issue. Please let me know what you suggest.

vipin1code commented 6 years ago

@silkimen I created a private repo for the demo project which contains all resources to replicate and test this issue. I have added you as a collaborator to that repo. Please let me know if you need anything else to try and replicate this issue.

Once it is fixed we can report the results here.

vipin1code commented 6 years ago

Hi @silkimen Have you been able to replicate this issue with the private repo I shared? Was that helpful in recreating this issue on your end? Please let me know if you think the issue can be fixed. Also is there any Gitter chatroom specifically for this plugin? Thanks

keithdmoore commented 6 years ago

@ravi-pandit14 @mrvipinkashyap Have you guys tried version 2.0.0 or above for this plugin? Looks like the setSSLCertMode feature was added in 2.0.0 so you might try that. I had to force the install with ionic cordova plugin add cordova-plugin-advanced-http@2.0.1 to get the newer version.

vipin1code commented 6 years ago

@keithdmoore Thanks for checking. Yes, I am using v2.0.1 of plugin and all tests results I have added above is with latest version of plugin.

mm44m6 commented 6 years ago

I'm having the same issue with the v2.0.1. It works if the

nocheck

option is used but it doesn't work when the pinning is active or in

default

mode.

Pls fix this.

divyangsolanki commented 5 years ago

I am having the same issue. I am using v2.0.1. The same code is working in Android but not working in iOS for Cordova application.

mm44m6 commented 5 years ago

Ok, so I was having this issue and I realised I was putting the certificates folder in the wrong place so it was not actually finding it therefore it was not pinning and throwing this error.

After I placed the certs inside the correct folder, it worked fine. The certificates folder should be inside the www folder. Make sure it's in the right place or else it will keep failing.

Now, in Ionic 4, if anyone is using it, it's more tricky since when you build your app your www gets rewritten. To make it work I had to create a Cordova hook that copies the certificates folder from the root of the project and paste it inside the right folder inside each platform (./platforms/android/app/src/main/assets/www for Android and ./platforms/ios/www for iOS).

divyangsolanki commented 5 years ago

Hello @mm44m6 , I have attached one screenshot which shows my project folder structure.

screenshot 2018-11-23 at 2 40 52 pm

I have tried to put .cer file in certificates folder and add <resource-file src="hooks/certificates/certi.cer"/> in config.xml file for iOS but after building the application .cer file is inserted into /platforms/ios/resources folder. And the code is not working for iOS.

mm44m6 commented 5 years ago

@divyangsolanki Are you using Ionic 3 or 4? If you're using Ionic 3, you should place the certificates folder inside the www folder. www is located in the root of your project. This folder is created after you build your app for the first time.

captura de tela 2018-11-23 as 13 10 56
divyangsolanki commented 5 years ago

@mm44m6
No, actually I am not using ionic, I have developed my app using Cordova and vue js.

And in my www folder certificates folder is not created after building the application.

mm44m6 commented 5 years ago

@divyangsolanki Just create the certificates folder and put your certs inside it and then test your application. It should work just fine. I'll try to replicate your issue using only Cordova then.

divyangsolanki commented 5 years ago
screenshot 2018-11-27 at 3 52 57 pm

@mm44m6 I have attached my project folder structure where I put my certificates files. It is working fine in Android but not in iOS.

I have tried one solution to give certificate file path in config.xml file
For Platform Android:

<platform name="android">
<resource-file src="hooks/certificates/certi.cer" target="assets/www/certificates/certi.cer">
</platform>

For Platform iOS:

<platform name="ios">
<resource-file src="hooks/certificates/certi.cer">
</platform>

This solution is also not working.

silkimen commented 5 years ago

@divyangsolanki: you have to put your certs in www/certificates/ NOT in hooks/certificates/. This folder is not auto-generated, you need to create it manually. You don't need to include the cert files in your config.xml file.

divyangsolanki commented 5 years ago

I have tried to implement as per your suggestion but it is not working. I am always getting "Success" although I have put an invalid certificate in android.

zeidlos commented 5 years ago

We have the same problem and Can't figure out what's wrong. We're only getting back a "canceled".

mm44m6 commented 5 years ago

@zeidlos are you putting the certificates in the right folder? And also, are you using the right certificates for you endpoint? From what I've seen here, while trying to debug the native code, this error could be related to ssl issues. The error treatment in this plugin could be better... This message gives no clue whatsoever to why the pinning is failing.

divyangsolanki commented 5 years ago

@mm44m6 I have put my certificates in the right folder and I am using an invalid certificate to check whether error case is generated or not. But it is not working in iOS.

elin-y commented 5 years ago

@mm44m6 Hello Maria, can you share the hook you created? I'm using Ionic 3 but the www-Folder is not in our version control, so I need a way to put the certificates into the www folder automatically after the build process.

mm44m6 commented 5 years ago
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.

gbvacco commented 5 years ago

I'm having the same issue, anyone had success when pinning on iOS?

jratiwanich commented 5 years ago

Anyone has the solution for Ionic4 using this plugin? I manually copied the .cer file to platforms/ios/www/certificates/mycert.cer

but it's not working so far. I keep getting

error: "cancelled"
status: -1
silkimen commented 5 years ago

Closing this, feel free to open a new issue, if this won't solve your problem! 👍

kctang commented 2 years ago

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.

captain-programming commented 9 months ago

@kctang Hi,

I facing the same issue and I am frustrated but thank you are giving solution i will try and check if this is working are not.

Error:

image

captain-programming commented 9 months ago

@kctang Hi, Thanks. It's working.