Using React Native Keychain in Your Mobile Application

React Native Keychain is a library that helps keep your mobile application secure with the added convenience of enabling your users to unlock pieces of data by scanning their face, iris, or fingerprint.

Entering a username and password on each login is cumbersome and prone to input errors. That’s especially true with the increasing complexity of password requirements these days. This library makes it easy for your users to authenticate and is a breeze to install in your application.

Why Use This Library?

Once you add the library to your project, you’ll have access to a secure data store that will persist values even after reboots. This data store is secured by encrypting your data before you save it. The only way to decrypt your data is by verifying yourself using the embedded biometric hardware.

Good candidates for this storage option are login credentials, certificates, cookies, web tokens, or anything else that could identify a user. However, the primary requirement is that you store items as strings. If you wish to store any other data type, you’ll need to stringify it going in and transform it back to your desired data type after retrieval.

How to Install

First, you’ll need to run the following command to install the library

yarn add react-native-keychain && cd ios && pod install

Next, if you want to enable FaceID authentication on iOS, you’ll need to add a NSFaceIDUsageDescription key to your info.plist file.

<string>$(PRODUCT_NAME) Authentication with TouchId or FaceID</string>

Lastly, you’ll need to rebuild your app and restart your development server to begin using the library!

How to Use

First, import the library.

import * as Keychain from "react-native-keychain";

Next, you can save credentials in the secure data store like this:

 async () => {
    const username = "bobson"
    const password = "34e1a3f5"
    const result = await Keychain.setGenericPassword(username, password);

setGenericPassword will resolve an object on success and false on failure.

Then, you can retrieve the previously saved credentials.

 async () => {
    try {
      const result = await Keychain.getGenericPassword();
      // if there is a result, proceed with authentication
    } catch (e) {
      // if there is an error, fall back to another authentication option

getGenericPassword resolves false if no credentials are stored for the app. It will throw an error if the user closes the biometric prompt or if there is a problem decrypting the data. On success, an object will be returned with attributes for the username and password.

This method takes care of prompting the user to scan their face/iris/fingerprint. It’s really that easy!

Lastly, you can remove the credentials.

 async () => {
    const result = await Keychain.resetGenericPassword();

Testing with Jest

If any of these methods are part of your test coverage, you’ll need to write a mock for this library. Including a mock is necessary because this library needs access to the underlying device APIs in order to work, and those aren’t available when running on your computer. Here’s an example mock of the methods we used earlier:

jest.mock("react-native-keychain", () => {
  return {
    setGenericPassword: jest.fn().mockResolvedValue({}),
    getGenericPassword: jest.fn().mockResolvedValue({username: "bobson", password: "34e1a3f5"}),
    resetGenericPassword: jest.fn().mockResolvedValue(true),

Testing in iOS Simulator

You can then test this library in an iOS simulator. From my experience, it seems to work without any configuration. You may have to enroll FaceID or TouchID on your simulated device. You can do that in the Features menu item in the simulator’s menu bar. Also, when testing in a simulator, you will not see the prompt for biometric input. Rather the simulator will assume authentication succeeds and resolve the credentials.

Overall, I’m happy with how well this library worked on my current project. At first, I worried that interacting with devices’ secure storage would be complicated, but it’s really not with this library. I found that it wrapped up the complicated platform-specific logic in a programmer-friendly way that is similar to interacting with any other key/value store.