Recognized by Clutch.co as a top-rated Mobile App Development Company.
folio3-mobile
US 408 365 4638
START YOUR PROJECT
  • Solutions
    • Apps Discovery Services
    • Team Augmentation
    • Enterprise
    • AR/VR
    • IoT
    • Wearables
    • Field Sales
    • On Demand Apps
  • Industries
    • Retail
    • Agriculture
    • Healthcare
    • Pharmaceutical & Life Sciences
    • Manufacturing
    • Automotive
    • Logistics
    • Education
  • Technologies
    • Native Mobile Apps
      • iOS
      • Android
    • Cross Platform Apps
      • React Native
      • Flutter
      • Ionic
      • Xamarin
      • NativeScript
      • Sencha
  • Portfolio
  • Blog
  • Contact Us
  • Solutions
    • Apps Discovery Services
    • Team Augmentation
    • Enterprise
    • AR/VR
    • IoT
    • Wearables
    • Field Sales
    • On Demand Apps
  • Industries
    • Retail
    • Agriculture
    • Healthcare
    • Pharmaceutical & Life Sciences
    • Manufacturing
    • Automotive
    • Logistics
    • Education
  • Technologies
    • Native Mobile Apps
      • iOS
      • Android
    • Cross Platform Apps
      • React Native
      • Flutter
      • Ionic
      • Xamarin
      • NativeScript
      • Sencha
  • Portfolio
  • Blog
  • Contact Us

Login via Fingerprint in React Native

Published by: Noc Folio3 | March 12, 2020
SCROLL AND BE AMAZED!
Home > React Native > Login via Fingerprint in React Native

To keep up with the latest technology fingerprint authentication has become extremely popular in mobile apps these days. It secures the app and makes it a seamless authentication flow for the user.

While implementing this we had to go through a lot of brainstorming and concluded the following flow which we’ll be covering in this blog. Also one thing to keep in mind is this flow is recommended for the single user device and not shared devices.

We’ll be using two libraries for this feature:

  1. React-native-touch-id
  2. React-native-keychain

We’ve divided the implementation into TWO steps.

  1. Enable fingerprint from the application’s setting.
  2. Login via fingerprint.

Enable fingerprint from application setting

On the user’s action to ā€œenable fingerprintā€ we’ll be checking if the fingerprint is supported by OS and device. For that we need to:

1. Install React-native-touch-id.

npm i --save react-native-touch-id

or

yarn add react-native-touch-id

2. Then link the library to the project

react-native link react-native-touch-id

On iOS, you can also link package by updating your podfile

pod 'TouchID', :path => "#{node_modules_path}/react-native-touch-id"

And then run

pod install

3. Add the following permissions to their respective files:

In your AndroidManifest.xml:

<uses-permission android:name="android.permission.USE_BIOMETRIC" />

In your Info.plist:

<key>NSFaceIDUsageDescription</key>
 <string>Enabling Face ID allows you quick and secure access to your account.</string> 

Now create a service `biometricService.js` and add `checkBiometricSupportednEnrolled` method.

import TouchID from 'react-native-touch-id';
export const checkBiometricSupportednEnrolled = async () => {
   const optionalConfigObject = {
       unifiedErrors: false, // use unified error messages (default false)
       passcodeFallback: false // if true is passed, it will allow isSupported to return an error if the device is not enrolled in touch id/face id etc. Otherwise, it will just tell you what method is supported, even if the user is not enrolled.  (default false)
   }
   return new Promise((resolve, reject) => {
       //isSupported returns both cases 1. if supported 2. Is enabled/configured/enrolled
       TouchID.isSupported(optionalConfigObject)
           .then(biometryType => {
               // Success code.
         // as we are focusing on fingerprint for now 
               if (biometryType && biometryType != 'FaceID') {
                   resolve(true);
               } else {
             let fingerprintLableForOS = Platform.OS == "ios" ? "Touch ID" : "Fingerprint";
                   reject( fingerprintLableForOS + " is not available on this device");
               }
           })
           .catch(error => {
               // iOS Error Format and android error formats are different
               // android use code and ios use name
               // check at https://github.com/naoufal/react-native-touch-id
               let errorCode = Platform.OS == "ios" ? error.name : error.code;
               if (errorCode === "LAErrorTouchIDNotEnrolled" || errorCode === "NOT_AVAILABLE" || errorCode === "NOT_ENROLLED") {
             let fingerprintLableForOS = Platform.OS == "ios" ? "Touch ID" : "Fingerprint";
                   resolve(fingerprintLableForOS + " has no enrolled fingers. Please go to settings and enable " + fingerprintLableForOS + " on this device.");
               } else {
                   reject(Platform.OS == "ios" ? error.message : translations.t(error.code));
               }
           });
   });
}

This service method will return true if the fingerprint is supported and one or more fingerprints are already enrolled on the device else it will return error code. You can handle different types of errors according to your case. For now, we just want to handle LAErrorTouchIDNotEnrolled for iOS, NOT_ENROLLED for android, which means fingerprint is supported but there are no enrolled fingers. We’ll also show redirection alert [redirect to device settings] on these errors.

Call this service

let isFingerPrintSupported = yield call(KeychainService.checkBiometricSupportednEnrolled); 

and add

if (isFingerPrintSupported === true) {
       //fingerprint is supported and enrolled
       //TODO: we’ll work here in the next step
} else {
       //show alert "TouchID has no enrolled fingers. Please go to settings and enable fingerprint on this device." that we returned from the service
       Alert.alert(
         "Alert",
         isFingerPrintSupported,
         [{
           text: 'Ok', onPress: () => {
             //redirect to settings
             Platform.OS === "ios"
               ? Linking.openURL('app-settings:')
               : AndroidOpenSettings.securitySettings() // Open security settings menu
           }
         }]
);

On getting supported and enrolled responses from the service we need to save current user’s credentials to Keystore [for android] or keychain [for iOS].

For this purpose, we need to install React-native-keychain.

yarn add react-native-keychain
react-native link react-native-keychain

Re-build your Android and iOS projects and create a new service `keychainService.js` and add method `setCredentials`.

import * as Keychain from 'react-native-keychain';
import { Platform } from "react-native";
export const setCredentials = async (username, password) => {
   return new Promise((resolve, reject) => {
       // Store the credentials
       Keychain.setGenericPassword(username, password)
           .then(resp => {
               resolve(true)
           })
           .catch(err => {
               console.log("err: ", err);
               reject(err);
           });
   });
}

Now we’ll call this function from the `if` condition we left empty earlier.

if (isFingerPrintSupported === true) {
    yield call(KeychainService.setCredentials, user_name, JSON.stringify({password}));
}

setGenericPassword is limited to strings only, so if you need to store objects, etc, please use JSON.stringify/JSON.parse when you store/access it.

Till now our first section is completed. You can play around with both of these libraries and use it for faceID too.

Authenticate via fingerprint

On application launch, if the user is not logged in already we’ll check if our keychain contains login credentials or not. For that, we need to add another function in our `keychainService.js` as `getCredentials` which will return saved keychain credentials.

export const getCredentials = async () => {
   return new Promise((resolve, reject) => {
       Keychain.getGenericPassword()
           .then((credentials) => {
               if (credentials && credentials.username) {
                   // console.log('Credentials successfully loaded for user ' + credentials.username);
                   resolve(credentials);
               } else {
                   // console.log('No credentials stored');
                   resolve(null);
               }
           })
           .catch(err => {
               console.log("err: ", err);
               reject(err);
           });
   });
}

And call this function by dispatching action in your login’s componentWillMount.

 let credentials = yield call(KeychainService.getCredentials);
     if (credentials && credentials.username)) {
    let isFingerPrintSupported = yield call(KeychainService.checkBiometricSupportednEnrolled);
 
    if (isFingerPrintSupported === true) {
            // show fingerprint alert on login page
        // and authenticate FingerPrint when user touch the sensor
}
     } else {
       // else don’t show fingerprint option on login
     }

Use `checkBiometricSupportednEnrolled` to check if the fingerprint is still enrolled and show login via fingerprint modal on the login screen.

Now there can be two ways in which the user can log in:

1. Login with fingerprint

We need to authenticate the user’s fingerprint when he touches the sensor. For this make a function in our `biometricService.js` as `authenticateFingerPrint`.

export const authenticateFingerPrint = () => {
   return new Promise((resolve, reject) => {
    // configuration object for more detailed dialog setup and style:
       // const optionalConfigObject = {
       //     title: 'Authentication Required', // Android
       //     imageColor: '#e00606', // Android
       //     imageErrorColor: '#ff0000', // Android
       //     sensorDescription: 'Touch sensor', // Android
       //     sensorErrorDescription: 'Failed', // Android
       //     cancelText: 'Cancel', // Android
       //     fallbackLabel: 'Show Passcode', // iOS (if empty, then label is hidden)
       //     unifiedErrors: false, // use unified error messages (default false)
       //     passcodeFallback: false, // iOS - allows the device to fall back to using the passcode, if faceid/touch is not available. this does not mean that if touchid/faceid fails the first few times it will revert to passcode, rather that if the former are not enrolled, then it will use the passcode.
       // };
  let fingerprintLableForOS = Platform.OS == "ios" ? "Touch ID" : "Fingerprint";
 
       TouchID.authenticate('Login to [appname] using ' + fingerprintLableForOS)
           .then(success => {
               // console.log('Authenticated Successfully', success)
               resolve(success)
           })
           .catch(error => {
               console.log('Authentication Failed', error.code)
               reject(error)
           });
   });
}

If authentication is successful then login to the server using saved credentials in keychain/Keystore.

let isFingerPrintAuthenticated = yield call(KeychainService.authenticateFingerPrint);
 
 if (isFingerPrintAuthenticated === true) {
   let credentials = yield call(KeychainService.getCredentials);
     if (credentials && credentials.username) {
     let savedPassword = JSON.parse(credentials.password),
           savedUsername = credentials.username,
           requestData = {};
 
           requestData['user_name'] = savedUsername;
           requestData['password'] = savedPassword.password;
    }
  // login with saved credentials
         yield put({ type: "LOGIN_REQUESTED", requestData });
}

2. Login with credentials

Users can also cancel fingerprint popups and login via username and password. There can be two cases.

  1. The user whose credentials are already saved logs in
  2. Another user logs in

On credentials submitted, we’ll check if credentials match with the stored ones.

//check if saved username in keychain/keystore is same as data then continue
//else reset credentials 
//or update credentials using setCredentials after successful login if password is //different from the saved one
     let credentials = yield call(KeychainService.getCredentials);
     if (credentials && credentials.username != user_name) {
yield call(KeychainService.resetCredentials);
     }
//login to server
     const loggedinUser = yield call(AuthService.login, action.requestData);

And add `resetCredentials` function in `keychainService.js`

export const resetCredentials = async () => {
   return new Promise((resolve, reject) => {
       Keychain.resetGenericPassword()
           .then((response) => {
               // console.log('response', response);
               resolve(response);
           })
           .catch(err => {
               console.log("err: ", err);
               reject(err);
           });
   });
}

About Noc Folio3

Newsletter

Search

Archives

  • December 2023
  • April 2023
  • March 2023
  • October 2022
  • September 2022
  • August 2022
  • July 2022
  • June 2022
  • April 2022
  • March 2022
  • February 2022
  • October 2021
  • September 2021
  • May 2021
  • February 2021
  • January 2021
  • December 2020
  • November 2020
  • October 2020
  • May 2020
  • April 2020
  • March 2020
  • February 2020
  • January 2020
  • December 2019
  • November 2019
  • October 2019
  • September 2019
  • August 2019
  • July 2019
  • May 2019

Recent Posts

  • Exploring Flutter Navigation: From Basics to Advanced Routes
  • Web UI Test Automation with Pytest-BDD
  • How to fix IOS compass calibration issues
  • Testing Android Applications With Perfect Coverage
  • How to use useRef hook efficiently? – React

Tags

  • android
  • angular-state-management
  • Automation
  • Compass
  • cross-platform
  • css
  • development
  • firebase
  • hooks
  • ios
  • learn-ngrx
  • ngrx-beginner
  • ngrx/store
  • QA
  • react-native
  • reactjs
  • scss
  • stylesheet
  • styling
  • Testing
  • Test Script
  • UI-UX

Newsletter

Newsletter

Post navigation

Previous React Native vs Swift: Which One is Best to Create an iOS App?
Next How to turn on-off developer options in Android
Schedule an Appointment with our Mobile App Development Expert
Footer Menu
  • Company
    • About Us
    • Portfolio
    • Blog
    • Careers
    • Contact Us
  • Solutions
    • Apps Discovery Services
    • Team Augmentation
    • Enterprise App Development
    • AR/VR Application Development
    • IoT Application Development
    • Wearables Apps Development
    • Field Sales
    • On-Demand Apps Development
  • Technologies
    • iOS
    • Android
    • React Native
    • Flutter
    • Ionic
    • Xamarin
    • NativeScript
    • HTML5
    • Sencha
  • Industries
    • Retail
    • Agriculture
    • Healthcare
    • Pharmaceutical
    • Manufacturing
    • Automotive
    • Logistics
    • Education

US Office

Belmont, California – 1301 Shoreway Road, Suite 160, Belmont, CA 94002

Pleasanton, California – 6701 Koll Center Parkway, #250 Pleasanton, CA 94566

Tel: +1 408 365 4638
Support: +1 (408) 512 1812

Mexico Office

Amado Nervo #2200, Edificio Esfera 1 piso 4, Col. Jardines del Sol, CP. 45050, Zapopan, Jalisco, Mexico

Bulgaria Office

49 Bacho Kiro Street, Sofia, 1000, Bulgaria

Canada Office​

895 Don Mills Road, Two Morneau Shepell Centre, Suite 900, Toronto, Ontario, M3C 1W3, Canada

UK Office

Export House, Cawsey Way, Woking Surrey, GU21 6QX

Tel: +44 (0) 14 8361 6611

UAE Office

Dubai, UAE – Dubai Internet City, 1st Floor, Building Number 12, Premises ED 29, Dubai, UAE

Tel: +971-55-6540154
Tel: +971-04-2505173

Pakistan Office

Folio3 Tower, Plot 26, Block B, SMCH Society, Main Shahrah-e-Faisal, Karachi.

First Floor, Blue Mall 8-R, MM Alam Road Gulberg III, Lahore.

Tel: +92-21-3432 3721-4 

Ā© 2025, Folio3 Software Inc., All rights reserved.

  • Privacy policy and terms of use
  • Cookie Policy
Follow us on
Facebook-f Linkedin-in Instagram

Get a free app audit

[contact-form-7 id="3548" title="Float Banner Form"]