expo-local-authentication allows you to use FaceID and TouchID (iOS) or the Fingerprint API (Android) to authenticate the user with a face or fingerprint scan.

Platform Compatibility

Android DeviceAndroid EmulatoriOS DeviceiOS SimulatorWeb
⏱ Pending

expo install expo-local-authentication

If you're installing this in a bare React Native app, you should also follow these additional installation instructions.

import * as LocalAuthentication from 'expo-local-authentication';

Determine whether a face or fingerprint scanner is available on the device.

Returns a promise resolving to boolean value indicating whether a face or fingerprint scanner is available on this device.

Determine what kinds of authentications are available on the device.

Returns a promise resolving to an array containing LocalAuthentication.AuthenticationType.{FINGERPRINT, FACIAL_RECOGNITION}. A value of 1 indicates Fingerprint support and 2 indicates Facial Recognition support. Eg: [1,2] means the device has both types supported. If neither authentication type is supported, returns an empty array.

Determine whether the device has saved fingerprints or facial data to use for authentication.

Returns a promise resolving to boolean value indicating whether the device has saved fingerprints or facial data for authentication.

Attempts to authenticate via Fingerprint/TouchID (or FaceID if available on the device).
Note: When using the fingerprint module on Android, you need to provide a UI component to prompt the user to scan their fingerprint, as the OS has no default alert for it.
Note: Apple requires apps which use FaceID to provide a description of why they use this API. If you try to use FaceID on an iPhone with FaceID without providing infoPlist.NSFaceIDUsageDescription in app.json, the module will authenticate using device passcode. For more information about usage descriptions on iOS, see Deploying to App Stores.

  • options (object) -- An object of options.
    • promptMessage (string) -- A message that is shown alongside the TouchID or FaceID prompt. (iOS only)
    • fallbackLabel (string) -- Allows to customize the default Use Passcode label shown after several failed authentication attempts. Setting this option to an empty string disables fallback to device passcode. (iOS only)

Returns a promise resolving to an object containing success, a boolean indicating whether or not the authentication was successful, and error containing the error code in the case where authentication fails.

Since Android doesn't provide a default UI component, we've provided an example with one to help you get up and running:
import * as React from 'react';
import {
} from 'react-native';
import Constants from 'expo-constants';
import * as LocalAuthentication from 'expo-local-authentication';

export default class App extends React.Component {
  state = {
    authenticated: false,
    modalVisible: false,
    failedCount: 0,

  setModalVisible(visible) {
    this.setState({ modalVisible: visible });

  clearState = () => {
    this.setState({ authenticated: false, failedCount: 0 });

  scanFingerPrint = async () => {
    try {
      let results = await LocalAuthentication.authenticateAsync();
      if (results.success) {
          modalVisible: false,
          authenticated: true,
          failedCount: 0,
      } else {
          failedCount: this.state.failedCount + 1,
    } catch (e) {

  render() {
    return (
          this.state.modalVisible ? { backgroundColor: '#b7b7b7' } : { backgroundColor: 'white' },
              ? 'Reset and begin Authentication again'
              : 'Begin Authentication'
          onPress={() => {
            if (Platform.OS === 'android') {
            } else {

        {this.state.authenticated && <Text style={styles.text}>Authentication Successful! 🎉</Text>}

          <View style={styles.modal}>
            <View style={styles.innerContainer}>
              <Text>Sign in with fingerprint</Text>
                style={{ width: 128, height: 128 }}
              {this.state.failedCount > 0 && (
                <Text style={{ color: 'red', fontSize: 14 }}>
                  Failed to authenticate, press cancel and try again.
                onPress={async () => {
                <Text style={{ color: 'red', fontSize: 16 }}>Cancel</Text>

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignContent: 'center',
    paddingTop: Constants.statusBarHeight,
    padding: 8,
  modal: {
    flex: 1,
    marginTop: '90%',
    backgroundColor: '#E5E5E5',
    justifyContent: 'center',
    alignItems: 'center',
  innerContainer: {
    marginTop: '30%',
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  text: {
    alignSelf: 'center',
    fontSize: 22,
    paddingTop: 20,

Cancels the fingerprint authentication flow. See usage in example snack above.