
Hello, my name is Luiz and in this tutorial i'll teach you how to add a new layer of protection on the mobile side that will defend your app from Man in the Middle Attacks. So without any further ado lets get started!
Let’s say you’re connecting to your bank’s website or app. Generally, these apps rely on a system of Certificate Authorities (CAs)—big, trusted organizations that issue digital certificates. If your bank’s website or app presents a valid certificate issued by a recognized authority, your device says, “Yep, this checks out,” and sets up a secure (SSL/TLS) connection.
This works nicely most of the time. But there’s a weak spot: if somebody manages to create a fraudulent certificate that still looks valid to your device (for example, a certificate from a compromised or malicious CA), they can sneak in as a man-in-the-middle (MITM) using a proxy between your app and the server, then the attacker can then intercept your data, read it, or even alter it before sending to the server.
That’s where SSL Pinning (also called certificate pinning or public key pinning) steps in to save the day. Think of it as an extra piece of knowledge your app has—a secret handshake, if you will, that ensures it’s talking to the right server and nobody else.
Imagine you meet up with a close friend at a crowded venue. Sure, you could rely on them showing an official ID, but maybe you also have a special password or secret handshake you worked out in advance. If they don’t know that handshake, they’re not your friend—end of story.
Similarly, with SSL Pinning, your app “knows” exactly what the server’s certificate or public key looks like, because it’s stored—or “pinned”—in the app’s code. When your app tries to connect, it compares the server’s certificate to that pinned one. If they don’t match exactly, the app refuses to connect. This means even if a hacker has a seemingly legitimate certificate, it won’t fool the pinned check.
Securing your React Native app with SSL pinning can help protect against man-in-the-middle (MITM) attacks. Below, I’ll walk you through how to install and configure this library in both a plain React Native project (the “bare” workflow) and under the Expo Managed Workflow. We’ll also cover how to fetch the public key hashes from SSL Labs and how to test your pinning setup with Charles Proxy.
# npm
npm install react-native-ssl-public-key-pinning
# or yarn
yarn add react-native-ssl-public-key-pinning
cd ios && pod install && cd ..
.xcworkspace in Xcode and build. For Android, use npx react-native run-android or open it in Android Studio.Because Expo Go does not allow custom native modules, you can’t test SSL pinning using the default Expo Go client. Instead, you’ll need to create a custom development build or use a production build. Here’s the process:
# npm
npm install react-native-ssl-public-key-pinning
# or yarn
yarn add react-native-ssl-public-key-pinning
npx expo run:ios
npx expo run:android
This bundles the native module into your app so you can debug on a simulator or device.npx expo build:ios
npx expo build:android
(Or use the newer EAS Build system.)expo-dev-client’s network inspector (which can interfere with pinning).npx expo install expo-build-properties
app.json or app.config.js, add:{
"expo": {
"plugins": [
[
"expo-build-properties",
{
"ios": {
"networkInspector": false
}
}
]
]
}
}
npx expo prebuild
npx expo run:ios) so these settings take effect.A crucial part of SSL pinning is embedding the server’s public key hashes in your code. One easy way to retrieve these hashes is via SSL Labs:

mEflZT5enoR1FuXLgYYGqnVEoZvmf9c2bVBpiOjYQ0c=. You’ll use these in your code.Now that you have your base64-encoded SHA-256 public key hashes, it’s time to embed them in your app:
App.js or a top-level component):import { initializeSslPinning } from "react-native-ssl-public-key-pinning";
async function setupPinning() {
await initializeSslPinning({
"example.com": {
includeSubdomains: true, // Whether to pin subdomains as well
publicKeyHashes: [
"mEflZT5enoR1FuXLgYYGqnVEoZvmf9c2bVBpiOjYQ0c=",
"CLOmM1/OXvSPjw5UOYbAf9GKOxImEp9hhku9W90fHMk=", // Backup pin
],
// Optionally set an expiration date (yyyy-MM-dd) for your pins
// expirationDate: "2025-12-31",
},
// ...add more domains if needed
});
}
// Call setupPinning() early in your app’s lifecycle
setupPinning();
example.com will now be validated against these pins.import { addSslPinningErrorListener } from "react-native-ssl-public-key-pinning";
const subscription = addSslPinningErrorListener((error) => {
// Error details about domain or pin mismatch
console.warn("Pinning error on domain:", error.serverHostname);
});
// Clean up when unmounting or reloading
// subscription.remove();
Finally, confirm your SSL pinning by attempting a MITM attack using Charles Proxy:

I hope you enjoyed reading this article. If you have any questions or feedback, don't hesitate to reach out to me on my social media bellow. Have a great day!






Hello, I'm Luiz, a Software Engineer from São Paulo, Brazil. In this article, I will share some best practices for frontend development that can help...

Hello, I'm Luiz, a Software Engineer from São Paulo, Brazil. In this article, we will explore the concept of Error Boundaries in React, how they work,...

Learn how to safely reclaim tons of disk space on your Mac without touching system files. This guide covers everything from clearing hidden caches, lo...

Hello! My name is Luiz, and in this article, I'll guide you through the basics of creating a smart contract on the Stellar blockchain using the Soroba...

Hello, my name is Luiz and in this tutorial i'll teach you how to add a new layer of protection on the mobile side that will defend your app from Man...

Hello, I'm Luiz, a 26-year-old Software Engineer from São Paulo, Brazil. Today, I want to share some essential tips for debugging Android apps using R...

Hello this will be a quite different article where i share my notes while studying some topic/framework/language/technology in this section we will co...

Hello my name is Luiz and i'm a software engineer based in Brazil and today i'm going to explain how does react-relay works with Suspense from react,...

In this article i'll show you how to setup a static files CDN under Gitlab Organization using Gitlab Pages

In this article i'll talk about some tips to improove your gnome linux appearence to look like mine

Hello, I'm Luiz, a Software Engineer from São Paulo, Brazil. In this article, I will share some best practices for frontend development that can help...

Hello, I'm Luiz, a Software Engineer from São Paulo, Brazil. In this article, we will explore the concept of Error Boundaries in React, how they work,...

Learn how to safely reclaim tons of disk space on your Mac without touching system files. This guide covers everything from clearing hidden caches, lo...

Hello! My name is Luiz, and in this article, I'll guide you through the basics of creating a smart contract on the Stellar blockchain using the Soroba...

Hello, my name is Luiz and in this tutorial i'll teach you how to add a new layer of protection on the mobile side that will defend your app from Man...

Hello, I'm Luiz, a 26-year-old Software Engineer from São Paulo, Brazil. Today, I want to share some essential tips for debugging Android apps using R...

Hello this will be a quite different article where i share my notes while studying some topic/framework/language/technology in this section we will co...

Hello my name is Luiz and i'm a software engineer based in Brazil and today i'm going to explain how does react-relay works with Suspense from react,...

In this article i'll show you how to setup a static files CDN under Gitlab Organization using Gitlab Pages

In this article i'll talk about some tips to improove your gnome linux appearence to look like mine