React Native SSL Pinning is back! — iOS version

Javier Muñoz
Apr 27, 2018 · 4 min read

Actually, it never like “went away” in iOS, but we’ll keep the title honoring the first story with the Android version.

Finally! Got some time to write this for you guys, hope it isn’t too late. Please forgive me for I’m not an iOS developer myself, not a very experience now 😉. So. Let’s get to it.

There is very little about SSL pinning out there with React Native. I checked out some very good options, including react-native-pinch and react-native-trustkit-wrapper, claps for you guys 👏🏼👏🏼! Sadly, none of them convinced me to take their way, so I made the tough call: implement pinning the old-native way.

Some of you might say: “but the title says React Native! why would you do that!?” Here are my motivations:

  • react-native-pinch: which is like the most taken option - I believe. It provides you with a nice network API, just like RN’s fetch. But the thing is that I was not using fetch in my app, which would’ve made it way easier to take this option btw. And I was not willing to change the current library, I really like it — btw, it’s axios (pls, don’t yell at me). Additionally, this module wouldn’t let you specify PubliKey info, only the actual certificates, which leads to rebuild the app in case the certificate (for any reason) is compromised or just expires.
  • react-native-trustkit-wrapper: is a very nice approach for making a module implementing TrutKit (I used it in my Android implementation so I think I’m biased to it XD), but! — there’s always a but- it was not very straightforward as I read somewhere, and you would have to restart the app after first launch or so. Then I was not so convinced of using this module.

That said. I went with TrustKit for iOS and the results are very convincing, so this is it:

First of all, you’ll have to get TrustKit in your app, and you can do so using Pods or Carthage. I prefer Carthage so I used it. Setup is very easy, you can go through the Getting Started documentation to get a better understanding of what we’re doing here.

In your XCode project, add TrustKit Framework as an embedded binary to your app’s target. Then add the configuration needed to initialize TrustKit. The latter can be done in two ways: programmatically or using Info.plist file. I used an altered or extended version of the Info.plist file because I have more build configurations other that the default Debug and Release RN projects come with.

In the background, TrustKit reads the Info.plist file in order to create a dictionary to initialize itself, so when you add your configuration to Info.plist, it reads the file, creates a dictionary and gets initialized automatically without you having to write any code. Based on that, I added a few lines of code to initialize TrustKit programmatically with all the configuration needed located in different .plist files, and TrustKit will be configured depending on which build configuration (environment) you want to deploy for.

Firs step, we’re going to create those configuration files. Go to your project folder, right click, New file… Select Property list file type and name it properly. Do this for as many build configuration or environments as you have or need.

Now, go to your target’s Build settings and add a User defined setting. We’re going to call it TK_CONFIG. You will be able to specify a value for every build configuration you have. In my case, I put the file name of the corresponding .plist file without the extension. This is because I placed those files in the project’s folder root. If you want to place them elsewhere, just make sure you specify the right path to the file.

We’re almost done. Now we’ll add the code I mentioned before in our AppDelegate.m file and we’re ready to go. Open the AppDelegate.m file and put this inside didFinishLaunchingWithOptions method before anything else:

NSString *fileName = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), (__bridge CFStringRef)@"TK_CONFIG_FILE");NSString *thePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"plist"];NSDictionary *properties = [NSDictionary dictionaryWithContentsOfFile:thePath];[TrustKit initSharedInstanceWithConfiguration:properties];

And that’s it! TrustKit will be ready to work and make sure SSL Pinning rises your app’s security. There are only a couple things you have to make sure:

  • Put the code above as the first thing in the method, otherwise TrustKit won’t work properly in your app.
  • Add TSKSwizzleNetworkDelegates as true in your configuration file. This will instruct TrustKit to modify your app’s network delegates. That’s right, the ones that React Native uses for networking.

That’d be all! It’s more easier to do than reading this story 😉. Please leave a comment if I missed something and a big THANKS for taking the time of reading this, really hope it helped!

Javier Muñoz

Written by

Mobile/Android enthusiast, learner and musician.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade