/* * File: SetupBiometricScreen.tsx * Description: Screen for setting up and authenticating with device biometrics or PIN. * Design & Developed by Tech4Biz Solutions * Copyright (c) Spurrin Innovations. All rights reserved. */ import React, { useState, useEffect } from 'react'; import { View, Text, TouchableOpacity, Alert, StyleSheet, SafeAreaView, } from 'react-native'; import ReactNativeBiometrics, { BiometryTypes, BiometryType, } from 'react-native-biometrics'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { Colors, Spacing, Typography, Shadows } from '../../../../shared/src/theme'; import { BASE_URL } from '../../../constants/URLS'; const PAYLOAD = 'neo-scan-secure-payload'; // A static payload for signature /** * SetupBiometricScreen - Manages user authentication using the device's * built-in biometrics or PIN/password. */ const SetupBiometricScreen: React.FC = () => { const [isAuthenticated, setIsAuthenticated] = useState(false); const [biometryType, setBiometryType] = useState(null); const [isAvailable, setIsAvailable] = useState(false); const rnBiometrics = new ReactNativeBiometrics({ allowDeviceCredentials: true }); console.log('base url',BASE_URL) useEffect(() => { checkBiometricAvailability(); checkAuthStatus(); }, []); const checkBiometricAvailability = async () => { try { const { available, biometryType: bioType } = await rnBiometrics.isSensorAvailable(); setIsAvailable(available); setBiometryType(bioType || null); } catch (error) { console.error('Biometric check failed:', error); Alert.alert('Error', 'Could not check for biometric features.'); } }; const checkAuthStatus = async () => { try { const authStatus = await AsyncStorage.getItem('isAuthenticated'); setIsAuthenticated(authStatus === 'true'); } catch (error) { console.error('Auth status check failed:', error); } }; const handleSuccessfulAuth = async () => { setIsAuthenticated(true); await AsyncStorage.setItem('isAuthenticated', 'true'); Alert.alert('Success', 'Authentication successful!'); }; const authenticateUser = async () => { if (!isAvailable) { Alert.alert('Not Available', 'Biometrics are not supported on this device.'); return; } try { // Check if keys exist. If not, create them. const { keysExist } = await rnBiometrics.biometricKeysExist(); if (!keysExist) { await rnBiometrics.createKeys(); } // Create a signature to authenticate. This will fallback to device PIN. const { success, signature } = await rnBiometrics.createSignature({ promptMessage: 'Authenticate', payload: PAYLOAD, }); if (success && signature) { // In a real app, you would verify the signature on your server. // For this example, we'll assume it's valid. await handleSuccessfulAuth(); } else { Alert.alert('Authentication Failed', 'You could not be authenticated.'); } } catch (error) { console.error('Authentication failed:', error); Alert.alert('Error', 'An unexpected error occurred during authentication.'); } }; const getBiometricTypeText = () => { switch (biometryType) { case BiometryTypes.TouchID: return 'Touch ID'; case BiometryTypes.FaceID: return 'Face ID'; case BiometryTypes.Biometrics: return 'Fingerprint'; default: return 'Device Credentials'; } }; const logout = async () => { try { setIsAuthenticated(false); await AsyncStorage.setItem('isAuthenticated', 'false'); } catch (error) { console.error('Logout failed:', error); } }; return ( {isAuthenticated ? ( Welcome! You are successfully authenticated. Logout ) : ( Authentication Required {isAvailable ? ( Use {getBiometricTypeText()} or your device PIN to continue. ) : ( Biometrics not available. Please use your device PIN to continue. )} Authenticate )} ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: Colors.backgroundAlt, }, content: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: Spacing.lg, }, title: { fontFamily: Typography.fontFamily.bold, fontSize: Typography.fontSize.title, color: Colors.textPrimary, marginBottom: Spacing.md, textAlign: 'center', }, subtitle: { fontFamily: Typography.fontFamily.regular, fontSize: Typography.fontSize.md, color: Colors.textSecondary, textAlign: 'center', marginBottom: Spacing.xl, paddingHorizontal: Spacing.lg, }, button: { backgroundColor: Colors.primary, paddingHorizontal: Spacing.xl, paddingVertical: Spacing.md, borderRadius: 8, marginVertical: Spacing.sm, ...Shadows.sm, minWidth: '80%', alignItems: 'center', }, buttonText: { color: Colors.background, fontSize: Typography.fontSize.md, fontFamily: Typography.fontFamily.bold, }, }); export default SetupBiometricScreen;