Fingerprint authentication in expo
Tags: javascript, reactnative, beginners, tutorial
Published: 2022-08-07 14:21:00

We have seen apps that use Biometric Prompts as a layer of security in the application.

![Finger print](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5yuf8ya4vfy3ypdjmzmv.gif)

Implementing this in expo is really easy. You can find the complete code for this at [this link](https://github.com/ChinmayMhatre/RN_fingerprint).

## Screens

This app will have two screens.

-   `Home`
-   `Start`

To give a brief, the `Start` screen will have the authentication button. When the user clicks on this button, the app will ask for the biometric prompt. If the user successfully authenticates, the app will navigate to the `Home` screen.

## App.js

`App.js` is used to setup our stack navigator between the two screens `Home` and `Start`.

```jsx
<NavigationContainer>
    <Stack.Navigator initialRouteName="Start">
        <Stack.Screen
            name="Start"
            component={Start}
            options={{ headerShown: false }}
        />
        <Stack.Screen name="Home" component={HomeScreen} />
    </Stack.Navigator>
</NavigationContainer>
```

## `Start.js`

We will import the `expo-local-authentication` package . This package allows you to use faceID and TouchID in IOS devices and Biometric Prompt in Android devices.

```jsx
import * as LocalAuthentication from "expo-local-authentication";
```

We create two states to check if the device supports biometric and if any fingerprint is saved in the device.

```jsx
const [isBiometricSupported, setIsBiometricSupported] = useState(false);
const [fingerprint, setFingerprint] = useState(false);
```

We use the `hasHardwareAsync` method to check if the device supports biometric authentication. `isEnrolledAsync` checks if any fingerprint is saved in the device.

```jsx
useEffect(() => {
    (async () => {
        const compatible = await LocalAuthentication.hasHardwareAsync();
        setIsBiometricSupported(compatible);
        const enroll = await LocalAuthentication.isEnrolledAsync();
        if (enroll) {
            setFingerprint(true);
        }
    })();
}, []);
```

We create a simple page with a button to authenticate the user.
In case Biometric is not supported or doesn't have any registered fingerprints, we show a message. 
```jsx
<View style={styles.start}>
    <View style={{ justifyContent: "center", flex: 1, alignItems: "center" }}>
        {isBiometricSupported && fingerprint ? (
            <TouchableOpacity onPress={handle}>
                <Text style={styles.button}>Go to home</Text>
            </TouchableOpacity>
        ) : (
            <View>
                <Text>fingerprint not supported/ allocated</Text>
            </View>
        )}
    </View>
</View>
```

`handle` is a function that will authenticate the user.

```jsx
const handle = async () => {
    try {
        const biometricAuth = await LocalAuthentication.authenticateAsync({
            promptMessage: "Login with Biometrics",
            disableDeviceFallback: true,
            cancelLabel: "Cancel",
        });
        if (biometricAuth.success) {
            navigation.replace("Home");
        }
    } catch (error) {
        console.log(error);
    }
};
```

`aunthenticateAsync` is a method that will authenticate the user. we pass the following parameters.

-   `promptMessage`: This is the message that will be displayed to the user.
-   `disableDeviceFallback`: This is a boolean value that will disable the fallback option. When we fail to authenticate with fingerprint for several attempts the device falls back to the default password if disableDeviceFallback is set to `false`.
-   `cancelLabel`: This is the label for the cancel button.

If the authentication is successful we navigate to the `Home` screen. `navigation.replace` is a method we use so that the user doesn't see a back button to go back to the `Start` screen. unlike `navigation.navigate` which will push the new screen on top of the current screen, `navigation.replace` will replace the current screen with the new screen.