Biometric authentication with react-native-keychain
Tags: reactnative, biometric
Published: 2023-12-13 19:59:54


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iz4pr1ogmwo4tmszgzxy.png)
[react-native-keychain](https://www.npmjs.com/package/react-native-keychain) uses the native secure storage mechanisms provided by the operating systems (Keychain on iOS and Keystore on Android). This ensures that sensitive information is stored in a secure enclave, making it difficult for unauthorized access. For comparing most reliable library you can visit this [link](https://npmtrends.com/react-native-biometrics-vs-react-native-keychain-vs-react-native-touch-id). To use biometric authentication with react-native-keychain in a React Native app for both Android and iOS, you can follow these general steps:

---

##1. Installation:

`yarn add react-native-keychain && cd ios && pod install`
or
`npm i react-native-keychain && cd ios && pod install`

---

##2. Configuration:

**a) iOS:**

i) Add the following key-value pair to [Info.plist](https://github.com/Ajmal0197/RNDevLearnNew/blob/main/ios/RNDevLearnNew/Info.plist):

```
<key>NSFaceIDUsageDescription</key>
<string>$(EXECUTABLE_NAME) wants Biometric to enhance the security of your account.</string>
```

ii) Add `Keychain Sharing` capability in iOS with default selected keychain groups/bundle id:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ny3l87tayln3aqhb8wq2.png)

**b) Android:**
No configuration required.

---

## 3. Usage:

[App.jsx](https://github.com/Ajmal0197/RNDevLearnNew/blob/main/src/srcRNKeychainBiometric/App.jsx)

```
      <Button title="Biometric" onPress={callBiometric} />
```

[Biometric.js](https://github.com/Ajmal0197/RNDevLearnNew/blob/main/src/srcRNKeychainBiometric/utils/Biometric.js)
```
import * as Keychain from 'react-native-keychain';

// Function to check if biometric authentication is supported
const isBiometrySupported = async () => {
  try {
    const biometryType = await Keychain.getSupportedBiometryType();
    console.log('getSupportedBiometryType', biometryType);
    alert(biometryType);
    return !!biometryType;
  } catch (error) {
    console.log('Error checking biometry support:', error.message);
    alert(JSON.stringify(error.message));
    return false;
  }
};

// Function to save credentials with biometric protection
const saveCredentialsWithBiometry = async (username, password) => {
  try {
    await Keychain.setGenericPassword(username, password, {
      accessControl: Keychain.ACCESS_CONTROL.BIOMETRY_ANY,
      accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED,
    });
    console.log('Credentials saved successfully with biometry protection in keychain');
    alert(JSON.stringify('Credentials saved successfully with biometry protection in keychain'));
  } catch (error) {
    console.log('Error saving credentials:', error.message);
    // Handle specific errors (e.g., user canceled biometric enrollment)
    if (error.name === 'BiometryEnrollmentCancel') {
      console.log('Biometric enrollment canceled by the user.');
      alert(JSON.stringify('Biometric enrollment canceled by the user.'));
    } else {
      console.log('Unknown error:', error);
      alert(JSON.stringify(error.message));
    }
  }
};

// Function to retrieve credentials with biometric authentication
const getCredentialsWithBiometry = async () => {
  try {
    const credentials = await Keychain.getGenericPassword({
      accessControl: Keychain.ACCESS_CONTROL.BIOMETRY_ANY,
    });
    return credentials;
  } catch (error) {
    console.log('Error retrieving credentials:', error.message);
    alert(JSON.stringify(error.message));
    // Handle specific errors (e.g., biometric authentication failed)
    if (error.message.includes('authentication failed')) {
      console.log('Biometric authentication failed.');
      alert(JSON.stringify('Biometric authentication failed.'));
    } else {
      console.log('Unknown error:', error);
      alert(JSON.stringify(error));
    }
    return null;
  }
};

// Example usage
const callBiometric = async () => {
  const biometrySupported = await isBiometrySupported();

  if (biometrySupported) {
    // Save credentials with biometric protection
    await saveCredentialsWithBiometry('username', 'password');

    // Retrieve credentials with biometric authentication
    const credentials = await getCredentialsWithBiometry();

    if (credentials) {
      console.log('Username:', credentials.username);
      console.log('Password:', credentials.password);
      alert(JSON.stringify(credentials.username + credentials.password));
    } else {
      console.log('Biometric authentication failed or credentials not found.');
      alert(JSON.stringify('Biometric authentication failed or credentials not found.'));
    }
  } else {
    console.log('Biometry not supported on this device.');
    alert('Biometry not supported on this device.');
  }
};

export default callBiometric;
```