Search code examples
javascriptandroidcordovacordova-3

How to open a HTTPS page (with self signed certificate) in Android hybrid app


I'm working in an hybrid app with Cordova 3.1 in Android.

In my application I have to open a HTTPS page that is my development server configured with a self signed certificate.

If I open the URL direclty from a browser an exception appears but I can accept it. If I open the URL from a native app I can open the page implementing the method onReceivedSslError of WebViewClient.

But in the hybrid app with javascript, using window.open() I'm not being able to handle the ssl exception.

I have tried to install the certificate in Android 2.3.3 exporting the certificate to a .cer file and installing it with Settings > Security > Install from storage and accepting the exception in the browser but it still fails.

Any help? Thank you.

This is the AndroidManifest.XML

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.ApiManager" android:versionCode="1" android:versionName="1.0">  
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="18"/>  
<supports-screens android:smallScreens="false" android:normalScreens="true" android:largeScreens="false"/>  
<uses-permission android:name="android.permission.INTERNET"/>  
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>  
<!-- Push permissions -->  
<permission android:name="com.ApiManager.permission.C2D_MESSAGE" android:protectionLevel="signature"/>  
<uses-permission android:name="com.ApiManager.permission.C2D_MESSAGE"/>  
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>  
<uses-permission android:name="android.permission.WAKE_LOCK"/>  
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>  
<uses-permission android:name="android.permission.USE_CREDENTIALS"/>  
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
<application android:label="@string/app_name" android:debuggable="true" android:icon="@drawable/icon"> 
    <activity android:name=".ApiManager" android:label="@string/app_name" android:configChanges="orientation|keyboardHidden|screenSize" android:launchMode="singleTask"> 
        <intent-filter> 
            <action android:name="android.intent.action.MAIN"/>  
            <category android:name="android.intent.category.LAUNCHER"/> 
        </intent-filter>  
        <intent-filter> 
            <action android:name="com.ApiManager.ApiManager.NOTIFICATION"/>  
            <category android:name="android.intent.category.DEFAULT"/> 
        </intent-filter> 
    </activity>  
    <!-- Preference Activity  -->  
    <activity android:name="com.worklight.common.WLPreferences" android:label="Worklight Settings"></activity>  
    <!-- Push service  -->  
    <!-- In order to use the c2dm library, an application must declare a class with the name C2DMReceiver, in its own package, extending com.google.android.c2dm.C2DMBaseReceiver 
        It must also include this section in the manifest, replacing "com.google.android.apps.chrometophone" with its package name. -->  
    <service android:name=".GCMIntentService"/>  
    <service android:name=".ForegroundService"/>  
    <!-- Only google service can send data messages for the app. If permission is not set - any other app can generate it -->  
    <receiver android:name="com.google.android.gcm.GCMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND"> 
        <!-- Receive the actual message -->  
        <intent-filter> 
            <action android:name="com.google.android.c2dm.intent.RECEIVE"/>  
            <category android:name="com.ApiManager"/> 
        </intent-filter>  
        <!-- Receive the registration id -->  
        <intent-filter> 
            <action android:name="com.google.android.c2dm.intent.REGISTRATION"/>  
            <category android:name="com.ApiManager"/> 
        </intent-filter> 
    </receiver> 
</application> 
</manifest>

Solution

  • Other way I have found is to generate a CA and create certs using that CA, then you must copy the .cer in the mobile and import the .cer generated for the CA in Android "Settings > Security > Install from storage".

    openssl genrsa -out myownca.key 1024
    openssl req -x509 -new -key myownca.key -out myownca.cer -days 365 
    

    This is the .cer to install in the mobile.

    Then generate certs using that CA to be used by the servers

    openssl genrsa -out mycert.key 1024 
    openssl req -new -out mycert.req -key mycert.key 
    openssl x509 -req -in mycert.req -out mycert.cer -CAkey myownca.key -CA myownca.cer -days 365 -CAcreateserial -CAserial serial 
    openssl pkcs12 -export -out mykeystore.p12 -inkey mycert.key -in mycert.cer -certfile myownca.cer
    

    This .p12 is the one to be used to import the new cert in the servers.

    For this last cert you must use a CN the hostname of the server machine.