A blog about my life, development and projects

Ionic Native HTTP

About a year or so back I created a mobile application for a client that was based on Ionic and was asked recently to add SSL pinning for security reason. During this I found and interesting behaviour that isn't very well documented and took me a while to discover.

In order to add SSL pinning I had to change the Http service calls from using Angular HTTP to Ionic Native Http. Everything was all good untill I had to make service calls.

But first, what is SSL Pinning: 

By default, when making an SSL connection, the client checks that the server’s certificate:

  • has a verifiable chain of trust back to a trusted (root) certificate
  • matches the requested hostname

What it doesn't do is check if the certificate in question is a specific certificate, namely the one you know your server is using.

Relying on matching certificates between the device's trust store and the remote server opens up a security hole. The device’s trust store can easily be compromised - the user can install unsafe certificates, thus allowing potential man-in-the-middle attacks.

Certificate pinning is the solution to this problem. It means hard-coding the certificate known to be used by the server in the mobile application. The app can then ignore the device’s trust store and rely on its own, and allow only SSL connections to hosts signed with certificates stored inside the application.

Adding SSL Pinning to an Ionic application:

The Ionic documentation is quite limited when it comes to examples. You can find it here https://ionicframework.com/docs/native/http/

Step 1: Install the required packages

$ ionic cordova plugin add cordova-plugin-advanced-http
$ npm install --save @ionic-native/http

Step 2: Add the plugin to the apps modules

import { HTTP } from '@ionic-native/http';

...

@NgModule({
...

providers: [
...
HTTP
...
]
...
})
export class AppModule { }

 

Step 3: Set SSL pining before making the HTTP service call

this._http.setSSLCertMode('pinned');

 

Issue 1: Now that SSL pinning is set, you can make the service call right? Wrong, the 1st issue was to actually specify the SSL certificate to use. The documentation didn't specify where the certificate should go, or what it should look like. I ended up creating a ".cer" file that consists only of the Public key (Please never distribute your private key). This certificate file I added to "/src/certificates" in my project. After this I had to update my Ionic asset copy to copy this file to "www/cerificates". Sure you could just add it directly to this folder, but I wanted it as part of the build in order to easily change it later on.

Now that the certificate is added the http calls started to work as expected. But some of the calls were still failing which leads to Issue 2.

Issue 2: After adding SSL pinning, the cerificate, and updating all my service calls from angular Http to Ionic Native Http some of the service calls were still failing. After some debugging, WireShark traces I discovered that Ionic Native Http by default sends all post requests as "application/x-www-form-urlencoded". This was fine for the basic calls as .Net Web Api can handle these things, even if it's expecting Json Rest calls, but the complex types were failing becouse they weren't parsed corectly.

The solution to this was simple. All I had to do was to set the Data Serializer for Ionic Native Http to Json. I wasted a lot of time on this which could have been solved if it was in the documentation, but here it is now for anyone else if they battle.

this._http.setDataSerializer('json');

 

Comments

Jak 2019/02/13 20:58:11

Great article. Have you tried this with Ionic4? It does not seem to work for me.

Dezi Van Vuuren 2019/02/14 05:51:06

Hi Jak

I haven't, I beleive it was Ionic 3. I can give it a try and let you know. I will reach out to you via email and see if I can assist further.

Jak 2019/02/14 19:29:12

Thank you. It would be nice to document where you put the cert file. In Ionic 4, I copied .cer file directly to e.g. platform/ios/www/certicates/mycert.cer
Perhaps i'm missing something else.

Dezi Van Vuuren 2019/02/18 06:18:43

I don't think copying it to platform/ios/www/certicates will work. The certificate needs to be in the build output folder of "www/certificates". If you look at the post I mentioned that you have to update the Ionic asset copy task to also copy certificates over. I think you can place the cert directly in there but during build it might be cleaned. The copy task is located under "node_modules/@ionic/app-scripts/config/copy.config.js". I added this into it for my project:
copyAssets: {
src: ['{{SRC}}/certificates/**/*'],
dest: '{{WWW}}/certificates'
},

Jintu Babu 2019/06/24 08:59:32

Great article!! I have implemented this in my current project but I am getting an issue "Plugin not installed". Is there any workaround for the same?

Dezi Van Vuuren 2019/06/24 09:07:06

Hi, have you ran these commands to install the plugins:
$ ionic cordova plugin add cordova-plugin-advanced-http
$ npm install @ionic-native/http

Post a comment

Categories