banner_for_undefined
Image credits: Rishi Chawda https://rishikc.com

Persist and Encrypt data in React Native applications

A Guide to Protecting User Privacy and Securing Data Storage

September 22, 2018  ·  3 min read

Users’ need for privacy and data security keeps increasing daily and it will always be in demand. So how do we store data on a mobile device without worrying about security? In this article, we’ll go through an effortless and quick way to:

  • Set up persistent storage for our app and store any user data locally.

  • Encrypt the data to make it secure so users feel less worried about their privacy.

So, let’s get started!


Persisting the data

First, we’ll set up persistent storage for our app. For this, we’ll use an excellent and easy-to-use library called redux-persist. Most of you must be familiar with redux. For those unfamiliar, it is a simple way to manage and share data in your React and React Native apps across various components and views. You can read more about it in my article on redux and how to use it in React and React Native apps.

Open the terminal and type the following command on your project’s root directory:

npm i redux-persist

This command will install redux-persist, which will help us to retain our data from previous sessions.

We’ll use redux-promise as our middleware for the examples in this article. You can use any middleware, like redux-saga or redux-thunk, based on your requirements!

Now let’s set up our store to make it persistent — so that the next time our app loads up, we’ll have data saved from the previous session. On your main store.js, set up persistent storage like this:

import { combineReducers, createStore, applyMiddleware } from 'redux';
import storage from 'redux-persist/lib/storage';
import { persistReducer, persistStore } from 'redux-persist';
import promise from 'redux-promise';
// Create the root reducer as you normally would.
const rootReducer = combineReducers({
myPersistentData: dataReducer,
someMorePresistentData: randomReducer,
});
/*
Create the configuration object to be used for transforming our simple
root reducer into a property on persistent storage.
*/
const config = {
key: '_myPersistentDataKey',
storage,
};
// Make your reducer persistent with persistReducer()
const reducer = persistReducer(config, rootReducer);
const store = createStore(
reducer, // Your persistent reducer
{}, // Initial store state
applyMiddleware(promise), // middleware(s)
);
// Convert your store to be persistent accross app sessions.
const persist = persistStore(store);
export default { store, persist };
view raw store.js hosted with ❤ by GitHub

In the main App.js file, modify the render function like this:

import { PersistGate } from "redux-persist/integration/react";
import { Provider } from "react-redux";

import store from "./store";
import MyRootComponent from "./src";

class App extends Component {
  constructor(props) {
    super(props);
    // ...
  }

  render() {
    return (
      <Provider store={store.store}>
        <PersistGate persistor={store.persist}>
          <MyRootComponent />
        </PersistGate>
      </Provider>
    );
  }
}

export default App;

That’s it! We’ve set up our redux state to be persistent! Easy.


Encrypting the persisted data

For this, we’ll use redux-persist-transform-encrypt. Run the following command on your project’s root directory:

npm i redux-persist-transform-encrypt

This will help us encrypt and decrypt user data across multiple sessions.

Note: Since this was just an example of how to encrypt your data, we hard-coded our secret key into the source code, but you must never do that! Ideally, it would be injected during our build process.

Now, open the store.js file again and update it to look like this:

import { combineReducers, createStore, applyMiddleware } from 'redux';
import storage from 'redux-persist/lib/storage';
import { persistReducer, persistStore } from 'redux-persist';
import promise from 'redux-promise';
import createEncryptor from 'redux-persist-transform-encrypt'; // <----- Import createEncryptor
const rootReducer = combineReducers({
myPersistentData: dataReducer,
someMorePresistentData: randomReducer,
});
/*
Configure your encryptor with the secret key
NOTE: This secret key is required for access to data.
If the key is incorrect or changed after storing data
with some different key, it will return null.
*/
const encryptor = createEncryptor({
secretKey: 'my-not-so-secret-encryption-key',
onError: (error) => {
console.warn('error occured on encryptor', error);
},
});
const config = {
key: '_myPersistentDataKey',
storage,
/* Add the encryptor as a transform property. This is will
tell the persistent storage to encrypt data using the
configuration given earlier,i.e., our secretKey. */
transforms: [encryptor], // <----- Add this line.
};
const reducer = persistReducer(config, rootReducer);
const store = createStore(
reducer,
{},
applyMiddleware(promise),
);
const persist = persistStore(store);
export default { store, persist };
view raw store.js hosted with ❤ by GitHub

Awesome! We made the data in our store state persistent locally, along with encryption! 🎉 👏

Congrats now we’ve encrypted our locally persisted react native application data.


Happy hacking! Cheers! 🎉