πŸ”₯ Secure Your React Native App with Biometric Authentication in Expo (2025 Guide) πŸ”

Any Techie
4 min read5 days ago

--

Learn how to implement biometric authentication (Face ID & Fingerprint) in your Expo Router app using Expo’s Local Authentication API!

Secure Your React Native App with Biometric Authentication in Expo
Secure Your React Native App with Biometric Authentication in Expo

πŸš€ Why Use Biometric Authentication in Mobile Apps?

Security is non-negotiable in mobile applications today. With the rise of cyber threats and data breaches, integrating biometric authentication (Face ID & Fingerprint) enhances security while offering a seamless user experience.

βœ… Faster Login & Authentication
βœ… No Need to Remember Passwords
βœ… Enhanced Security with Device-Level Protection

Expo makes it easy to implement biometric authentication without writing native code! πŸŽ‰

Secure your Expo React native App with Face ID & Fingerprint in just 5 steps
Secure your Expo React native App with Face ID & Fingerprint in just 5 steps

πŸ“Œ Step 1: Setting Up an Expo App with Router

Before we dive into authentication, let’s set up an Expo app using the latest Expo Router for modern file-based navigation.

Run the command below to create a new Expo app:

npx create-expo-stack@latest securityApp --expo-router
cd securityApp
npm install

πŸ“Œ This command creates a React Native app with Expo Router support!

πŸ“Œ Step 2: Install & Configure Biometric Authentication

Expo provides an easy-to-use Local Authentication API via expo-local-authentication. Let’s install it:

expo install expo-local-authentication

This package allows us to use Face ID & Fingerprint authentication without needing to eject our Expo project! πŸš€

πŸ“Œ Step 3: Implementing Biometric Authentication in Expo Router

Now, let’s create a lock screen that prompts users for biometric authentication before accessing the app.

πŸ”‘ Biometric Authentication Screen (/app/(modals)/lock.tsx)

import { SafeAreaView, Text, TouchableOpacity, StyleSheet } from "react-native";
import * as LocalAuthentication from "expo-local-authentication";
import { useRouter } from "expo-router";
import { useEffect, useState } from "react";
import * as Haptics from "expo-haptics";

export default function LockScreen() {
const [isBiometricAvailable, setIsBiometricAvailable] = useState(false);
const router = useRouter();
useEffect(() => {
checkBiometricAvailability();
}, []);
const checkBiometricAvailability = async () => {
const hasHardware = await LocalAuthentication.hasHardwareAsync();
const isEnrolled = await LocalAuthentication.isEnrolledAsync();
setIsBiometricAvailable(hasHardware && isEnrolled);
};
const authenticateUser = async () => {
const result = await LocalAuthentication.authenticateAsync({
promptMessage: "Authenticate to access the app",
fallbackLabel: "Use Passcode",
});
if (result.success) {
router.push("/");
} else {
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
}
};
return (
<SafeAreaView style={styles.container}>
<Text style={styles.title}>πŸ”’ Secure Access</Text>
<TouchableOpacity
style={styles.authButton}
onPress={authenticateUser}
disabled={!isBiometricAvailable}
>
<Text style={styles.authButtonText}>
{isBiometricAvailable ? "Authenticate with Face ID / Fingerprint" : "Biometrics Not Available"}
</Text>
</TouchableOpacity>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: { flex: 1, alignItems: "center", justifyContent: "center" },
title: { fontSize: 24, fontWeight: "bold", marginBottom: 20 },
authButton: { padding: 15, backgroundColor: "#3D38ED", borderRadius: 10 },
authButtonText: { color: "#fff", fontSize: 16, fontWeight: "bold" },
});

πŸ”Ή What’s happening here?
βœ… We check for biometric availability using LocalAuthentication.hasHardwareAsync()
βœ… If available, the app prompts users to authenticate
βœ… On success, the user is granted access to the app
βœ… If authentication fails, the app provides haptic feedback

πŸ“Œ Step 4: Auto-Locking the App on Inactivity πŸš€

To enhance security, let’s automatically lock the app when the user is inactive for 3 seconds.

πŸ›  User Inactivity Provider (/context/UserInactivity.tsx)

import { useRouter } from "expo-router";
import { useEffect, useRef } from "react";
import { AppState } from "react-native";
import { MMKV } from "react-native-mmkv";
const storage = new MMKV({ id: "UserInactivity" });
const LOCK_TIME = 3000; // Auto-lock after 3 seconds

export const UserInactivityProvider = ({ children }: any) => {
const appState = useRef(AppState.currentState);
const router = useRouter();
useEffect(() => {
const subscription = AppState.addEventListener("change", handleAppStateChange);
return () => {
subscription.remove();
};
}, []);
const handleAppStateChange = (nextAppState: any) => {
if (nextAppState === "background" || nextAppState === "inactive") {
router.push("/(modals)/lock");
} else if (nextAppState === "active" && appState.current.match(/inactive|background/)) {
const elapsed = Date.now() - (storage.getNumber("startTime") || 0);
if (elapsed >= LOCK_TIME) {
router.push("/(modals)/lock");
}
}
appState.current = nextAppState;
};
return children;
};

πŸ“Œ This ensures that if a user leaves the app for more than 3 seconds, they will have to re-authenticate! πŸ”

πŸ“Œ Step 5: Testing Biometric Authentication

πŸ”Ή Run your Expo app on a physical device:

npx expo start

iOS Users: Enable Face ID in Settings > Face ID & Passcode
Android Users: Enable Fingerprint Unlock in Security Settings

πŸ“Œ Final Thoughts & Next Steps

🎯 You just built a secure authentication system with biometrics in Expo!

βœ… Biometric authentication improves app security
βœ… Auto-locking feature protects user data
βœ… Expo makes this easy with expo-local-authentication

πŸ’‘ Want to take it further?
πŸ”Ή Integrate Expo SecureStore for password storage
πŸ”Ή Add Multi-Factor Authentication (MFA)
πŸ”Ή Implement JWT authentication for API security

πŸ”₯ What do you think about biometric authentication? Let me know in the comments! πŸš€πŸ‘‡

πŸ“Œ Follow me on LinkedIn for more React Native tips!
πŸ”— https://www.linkedin.com/in/prasadranjane32/

--

--

Any Techie
Any Techie

Written by Any Techie

0 Followers

πŸš€ Full-Stack & React Native Developer | Passionate about building scalable apps with React, Next.js, Node.js, & Expo | Tech Enthusiast & Problem Solver! πŸ”₯

No responses yet