refactor: rename package to RNAuthentication and update dependencies
feat: add postinstall script for patch-package fix: update react-native-biometrics to support device credentials refactor: remove FaceAuth, Home, LockScreen, Managelock, and related auth files chore: update TypeScript configuration for React Native
This commit is contained in:
183
App.tsx
183
App.tsx
@@ -1,166 +1,25 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
StyleSheet,
|
||||
TouchableOpacity,
|
||||
SafeAreaView,
|
||||
} from 'react-native';
|
||||
import Ionicons from '@react-native-vector-icons/ionicons';
|
||||
import { NavigationContainer } from '@react-navigation/native';
|
||||
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
||||
import HomeScreen from './HomeScreen';
|
||||
import LockScreen from './LockScreen';
|
||||
|
||||
const PIN_LENGTH = 4;
|
||||
const Stack = createNativeStackNavigator();
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [pin, setPin] = useState('');
|
||||
export default function App() {
|
||||
const [unlocked, setUnlocked] = useState(false);
|
||||
|
||||
const handlePress = (value: string) => {
|
||||
if (pin.length < PIN_LENGTH) {
|
||||
setPin(pin + value);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = () => {
|
||||
setPin(pin.slice(0, -1));
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<Text style={styles.title}>Verify Identity</Text>
|
||||
<Text style={styles.subtitle}>
|
||||
Use PIN, Fingerprint or Face ID
|
||||
</Text>
|
||||
|
||||
{/* PIN DOTS */}
|
||||
<View style={styles.pinRow}>
|
||||
{Array.from({ length: PIN_LENGTH }).map((_, i) => (
|
||||
<View
|
||||
key={i}
|
||||
style={[
|
||||
styles.pinDot,
|
||||
pin.length > i && styles.pinDotFilled,
|
||||
]}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
|
||||
{/* BIOMETRIC OPTIONS */}
|
||||
<View style={styles.bioRow}>
|
||||
<TouchableOpacity style={styles.bioBtn}>
|
||||
<Ionicons name="finger-print" size={36} color="#2563EB" />
|
||||
<Text style={styles.bioText}>Fingerprint</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity style={styles.bioBtn}>
|
||||
<Ionicons name="happy-outline" size={36} color="#2563EB" />
|
||||
<Text style={styles.bioText}>Face ID</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* KEYPAD */}
|
||||
<View style={styles.keypad}>
|
||||
{[1, 2, 3, 4, 5, 6, 7, 8, 9, '', 0, 'del'].map((item, index) => {
|
||||
if (item === '') {
|
||||
return <View key={index} style={styles.key} />;
|
||||
}
|
||||
|
||||
if (item === 'del') {
|
||||
return (
|
||||
<TouchableOpacity
|
||||
key={index}
|
||||
style={styles.key}
|
||||
onPress={handleDelete}
|
||||
>
|
||||
<Ionicons
|
||||
name="backspace-outline"
|
||||
size={26}
|
||||
color="#333"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
key={index}
|
||||
style={styles.key}
|
||||
onPress={() => handlePress(item.toString())}
|
||||
>
|
||||
<Text style={styles.keyText}>{item}</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
|
||||
};
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '#F8FAFF',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: 20,
|
||||
},
|
||||
title: {
|
||||
fontSize: 24,
|
||||
fontWeight: '700',
|
||||
marginTop: 40,
|
||||
color: '#111827',
|
||||
},
|
||||
subtitle: {
|
||||
fontSize: 14,
|
||||
color: '#6B7280',
|
||||
marginTop: 6,
|
||||
},
|
||||
|
||||
pinRow: {
|
||||
flexDirection: 'row',
|
||||
marginVertical: 28,
|
||||
},
|
||||
pinDot: {
|
||||
width: 14,
|
||||
height: 14,
|
||||
borderRadius: 7,
|
||||
borderWidth: 1.5,
|
||||
borderColor: '#2563EB',
|
||||
marginHorizontal: 8,
|
||||
},
|
||||
pinDotFilled: {
|
||||
backgroundColor: '#2563EB',
|
||||
},
|
||||
|
||||
bioRow: {
|
||||
flexDirection: 'row',
|
||||
marginBottom: 30,
|
||||
},
|
||||
bioBtn: {
|
||||
alignItems: 'center',
|
||||
marginHorizontal: 30,
|
||||
},
|
||||
bioText: {
|
||||
marginTop: 6,
|
||||
fontSize: 12,
|
||||
color: '#374151',
|
||||
},
|
||||
|
||||
keypad: {
|
||||
width: '80%',
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
key: {
|
||||
width: '33%',
|
||||
height: 70,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
keyText: {
|
||||
fontSize: 26,
|
||||
fontWeight: '500',
|
||||
color: '#111827',
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
export default App;
|
||||
return (
|
||||
<NavigationContainer>
|
||||
<Stack.Navigator screenOptions={{ headerShown: false }}>
|
||||
{!unlocked ? (
|
||||
<Stack.Screen name="Lock">
|
||||
{() => <LockScreen onUnlock={() => setUnlocked(true)} />}
|
||||
</Stack.Screen>
|
||||
) : (
|
||||
<Stack.Screen name="Home" component={HomeScreen} />
|
||||
)}
|
||||
</Stack.Navigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
}
|
||||
|
||||
10
HomeScreen.tsx
Normal file
10
HomeScreen.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import React from 'react';
|
||||
import { View, Text } from 'react-native';
|
||||
|
||||
export default function HomeScreen() {
|
||||
return (
|
||||
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
||||
<Text>Welcome! App Unlocked 🔓</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
89
LockScreen.tsx
Normal file
89
LockScreen.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { View, Text, Alert, StyleSheet, Platform } from 'react-native';
|
||||
import ReactNativeBiometrics, { BiometryTypes } from 'react-native-biometrics';
|
||||
|
||||
const rnBiometrics = new ReactNativeBiometrics({
|
||||
allowDeviceCredentials: true, // PIN / Pattern fallback
|
||||
});
|
||||
|
||||
type Props = {
|
||||
onUnlock: () => void;
|
||||
};
|
||||
|
||||
const LockScreen: React.FC<Props> = ({ onUnlock }) => {
|
||||
useEffect(() => {
|
||||
checkAndAuthenticate();
|
||||
}, []);
|
||||
|
||||
const checkAndAuthenticate = async () => {
|
||||
try {
|
||||
const { available, biometryType } =
|
||||
await rnBiometrics.isSensorAvailable();
|
||||
// const isSensorAvailable = await rnBiometrics.isSensorAvailable();
|
||||
// console.log('===============>', isSensorAvailable);
|
||||
if (!available) {
|
||||
Alert.alert(
|
||||
'Biometric not available',
|
||||
'Your device does not support biometric authentication.',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Biometry Type:', biometryType);
|
||||
|
||||
// Face ID / Face Unlock / Fingerprint handled by OS
|
||||
authenticate();
|
||||
} catch (error) {
|
||||
Alert.alert('Error', 'Failed to check biometric availability');
|
||||
}
|
||||
};
|
||||
|
||||
const authenticate = async () => {
|
||||
try {
|
||||
const { success } = await rnBiometrics.simplePrompt({
|
||||
promptMessage: 'Unlock App',
|
||||
cancelButtonText: 'Cancel',
|
||||
});
|
||||
|
||||
if (success) {
|
||||
onUnlock();
|
||||
} else {
|
||||
showRetryAlert();
|
||||
}
|
||||
} catch (error) {
|
||||
showRetryAlert();
|
||||
}
|
||||
};
|
||||
|
||||
const showRetryAlert = () => {
|
||||
Alert.alert(
|
||||
'Authentication Failed',
|
||||
'Unable to authenticate using Face ID / Biometrics.',
|
||||
[
|
||||
{ text: 'Retry', onPress: authenticate },
|
||||
{ text: 'Cancel', style: 'cancel' },
|
||||
],
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.text}>
|
||||
Authenticating using Face ID / Biometrics...
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default LockScreen;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
text: {
|
||||
fontSize: 16,
|
||||
},
|
||||
});
|
||||
35
README.md
35
README.md
@@ -95,3 +95,38 @@ To learn more about React Native, take a look at the following resources:
|
||||
- [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**.
|
||||
- [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts.
|
||||
- [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native.
|
||||
|
||||
<!-- node_modules/react-native-bometrics/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java -->
|
||||
|
||||
line no 185 to 214
|
||||
private BiometricPrompt.PromptInfo getPromptInfo(
|
||||
String promptMessage,
|
||||
String cancelButtonText,
|
||||
boolean allowDeviceCredentials
|
||||
) {
|
||||
BiometricPrompt.PromptInfo.Builder builder =
|
||||
new BiometricPrompt.PromptInfo.Builder()
|
||||
.setTitle(promptMessage);
|
||||
|
||||
builder.setAllowedAuthenticators(
|
||||
getAllowedAuthenticators(allowDeviceCredentials)
|
||||
);
|
||||
|
||||
if (!allowDeviceCredentials || isCurrentSDK29OrEarlier()) {
|
||||
builder.setNegativeButtonText(cancelButtonText);
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
|
||||
}
|
||||
|
||||
private int getAllowedAuthenticators(boolean allowDeviceCredentials) {
|
||||
int authenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK;
|
||||
|
||||
if (allowDeviceCredentials) {
|
||||
authenticators |= BiometricManager.Authenticators.DEVICE_CREDENTIAL;
|
||||
}
|
||||
|
||||
return authenticators;
|
||||
|
||||
}
|
||||
|
||||
@@ -77,18 +77,14 @@ android {
|
||||
buildToolsVersion rootProject.ext.buildToolsVersion
|
||||
compileSdk rootProject.ext.compileSdkVersion
|
||||
|
||||
namespace "com.authenticationsdk"
|
||||
namespace "com.rnauthentication"
|
||||
defaultConfig {
|
||||
applicationId "com.authenticationsdk"
|
||||
applicationId "com.rnauthentication"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
prefab true
|
||||
}
|
||||
signingConfigs {
|
||||
debug {
|
||||
storeFile file('debug.keystore')
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
|
||||
|
||||
<application
|
||||
android:name=".MainApplication"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.authenticationsdk
|
||||
package com.rnauthentication
|
||||
|
||||
import com.facebook.react.ReactActivity
|
||||
import com.facebook.react.ReactActivityDelegate
|
||||
@@ -11,7 +11,7 @@ class MainActivity : ReactActivity() {
|
||||
* Returns the name of the main component registered from JavaScript. This is used to schedule
|
||||
* rendering of the component.
|
||||
*/
|
||||
override fun getMainComponentName(): String = "authenticationsdk"
|
||||
override fun getMainComponentName(): String = "RNAuthentication"
|
||||
|
||||
/**
|
||||
* Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.authenticationsdk
|
||||
package com.rnauthentication
|
||||
|
||||
import android.app.Application
|
||||
import com.facebook.react.PackageList
|
||||
@@ -1,3 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">authenticationsdk</string>
|
||||
<string name="app_name">RNAuthentication</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") }
|
||||
plugins { id("com.facebook.react.settings") }
|
||||
extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
|
||||
rootProject.name = 'authenticationsdk'
|
||||
rootProject.name = 'RNAuthentication'
|
||||
include ':app'
|
||||
includeBuild('../node_modules/@react-native/gradle-plugin')
|
||||
|
||||
4
app.json
4
app.json
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"name": "authenticationsdk",
|
||||
"displayName": "authenticationsdk"
|
||||
"name": "RNAuthentication",
|
||||
"displayName": "RNAuthentication"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
module.exports = {
|
||||
presets: ['module:@react-native/babel-preset'],
|
||||
plugins: [
|
||||
'react-native-worklets-core/plugin',
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
iOS Biometric / Device Lock Setup
|
||||
|
||||
To enable and test device biometric authentication on iOS:
|
||||
|
||||
- Ensure the Info.plist contains a Face ID usage description (`NSFaceIDUsageDescription`). This project already adds a default string.
|
||||
- Install CocoaPods and native deps:
|
||||
|
||||
```sh
|
||||
cd ios
|
||||
bundle install # (if you use Bundler)
|
||||
bundle exec pod install
|
||||
```
|
||||
|
||||
- Open the workspace in Xcode (`ios/authenticationsdk.xcworkspace`) and build to a device or simulator. For Face ID testing use a simulator with Face ID enabled or a device with Face ID configured.
|
||||
- The app uses `react-native-keychain` to prompt for biometrics / device passcode; no additional Xcode entitlements are required beyond the Info.plist usage string.
|
||||
|
||||
If biometrics are not available, the Keychain prompt can fall back to the device passcode when configured.
|
||||
|
||||
Testing notes:
|
||||
- Simulator: Device > Face ID > Enrolled to simulate Face ID responses.
|
||||
- Device: Make sure Face ID / Touch ID is configured in Settings.
|
||||
2
index.js
2
index.js
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import { AppRegistry } from 'react-native';
|
||||
import App from './src/screen/authorised/AuthScreen.tsx';
|
||||
import App from './App';
|
||||
import { name as appName } from './app.json';
|
||||
|
||||
AppRegistry.registerComponent(appName, () => App);
|
||||
|
||||
@@ -14,7 +14,7 @@ if linkage != nil
|
||||
use_frameworks! :linkage => linkage.to_sym
|
||||
end
|
||||
|
||||
target 'authenticationsdk' do
|
||||
target 'RNAuthentication' do
|
||||
config = use_native_modules!
|
||||
|
||||
use_react_native!(
|
||||
|
||||
157
ios/Podfile.lock
157
ios/Podfile.lock
@@ -5,59 +5,9 @@ PODS:
|
||||
- FBLazyVector (0.83.1)
|
||||
- fmt (11.0.2)
|
||||
- glog (0.3.5)
|
||||
- GoogleDataTransport (9.4.1):
|
||||
- GoogleUtilities/Environment (~> 7.7)
|
||||
- nanopb (< 2.30911.0, >= 2.30908.0)
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
- GoogleMLKit/FaceDetection (6.0.0):
|
||||
- GoogleMLKit/MLKitCore
|
||||
- MLKitFaceDetection (~> 5.0.0)
|
||||
- GoogleMLKit/MLKitCore (6.0.0):
|
||||
- MLKitCommon (~> 11.0.0)
|
||||
- GoogleToolboxForMac/Defines (4.2.1)
|
||||
- GoogleToolboxForMac/Logger (4.2.1):
|
||||
- GoogleToolboxForMac/Defines (= 4.2.1)
|
||||
- "GoogleToolboxForMac/NSData+zlib (4.2.1)":
|
||||
- GoogleToolboxForMac/Defines (= 4.2.1)
|
||||
- GoogleUtilities/Environment (7.13.3):
|
||||
- GoogleUtilities/Privacy
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
- GoogleUtilities/Logger (7.13.3):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Privacy (7.13.3)
|
||||
- GoogleUtilities/UserDefaults (7.13.3):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilitiesComponents (1.1.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GTMSessionFetcher/Core (3.5.0)
|
||||
- hermes-engine (0.14.0):
|
||||
- hermes-engine/Pre-built (= 0.14.0)
|
||||
- hermes-engine/Pre-built (0.14.0)
|
||||
- MLImage (1.0.0-beta5)
|
||||
- MLKitCommon (11.0.0):
|
||||
- GoogleDataTransport (< 10.0, >= 9.4.1)
|
||||
- GoogleToolboxForMac/Logger (< 5.0, >= 4.2.1)
|
||||
- "GoogleToolboxForMac/NSData+zlib (< 5.0, >= 4.2.1)"
|
||||
- GoogleUtilities/UserDefaults (< 8.0, >= 7.13.0)
|
||||
- GoogleUtilitiesComponents (~> 1.0)
|
||||
- GTMSessionFetcher/Core (< 4.0, >= 3.3.2)
|
||||
- MLKitFaceDetection (5.0.0):
|
||||
- MLKitCommon (~> 11.0)
|
||||
- MLKitVision (~> 7.0)
|
||||
- MLKitVision (7.0.0):
|
||||
- GoogleToolboxForMac/Logger (< 5.0, >= 4.2.1)
|
||||
- "GoogleToolboxForMac/NSData+zlib (< 5.0, >= 4.2.1)"
|
||||
- GTMSessionFetcher/Core (< 4.0, >= 3.3.2)
|
||||
- MLImage (= 1.0.0-beta5)
|
||||
- MLKitCommon (~> 11.0)
|
||||
- nanopb (2.30910.0):
|
||||
- nanopb/decode (= 2.30910.0)
|
||||
- nanopb/encode (= 2.30910.0)
|
||||
- nanopb/decode (2.30910.0)
|
||||
- nanopb/encode (2.30910.0)
|
||||
- PromisesObjC (2.4.0)
|
||||
- RCT-Folly (2024.11.18.00):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
@@ -2031,35 +1981,6 @@ PODS:
|
||||
- ReactCommon/turbomodule/core
|
||||
- SocketRocket
|
||||
- Yoga
|
||||
- react-native-vector-icons-ionicons (12.3.0)
|
||||
- react-native-worklets-core (1.6.2):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
- fast_float
|
||||
- fmt
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly
|
||||
- RCT-Folly/Fabric
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-Core
|
||||
- React-debug
|
||||
- React-Fabric
|
||||
- React-featureflags
|
||||
- React-graphics
|
||||
- React-ImageManager
|
||||
- React-jsi
|
||||
- React-NativeModulesApple
|
||||
- React-RCTFabric
|
||||
- React-renderercss
|
||||
- React-rendererdebug
|
||||
- React-utils
|
||||
- ReactCodegen
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- SocketRocket
|
||||
- Yoga
|
||||
- React-NativeModulesApple (0.83.1):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
@@ -2617,7 +2538,7 @@ PODS:
|
||||
- React-perflogger (= 0.83.1)
|
||||
- React-utils (= 0.83.1)
|
||||
- SocketRocket
|
||||
- RNCAsyncStorage (2.2.0):
|
||||
- RNScreens (4.19.0):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
- fast_float
|
||||
@@ -2637,15 +2558,17 @@ PODS:
|
||||
- React-jsi
|
||||
- React-NativeModulesApple
|
||||
- React-RCTFabric
|
||||
- React-RCTImage
|
||||
- React-renderercss
|
||||
- React-rendererdebug
|
||||
- React-utils
|
||||
- ReactCodegen
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- RNScreens/common (= 4.19.0)
|
||||
- SocketRocket
|
||||
- Yoga
|
||||
- RNKeychain (10.0.0):
|
||||
- RNScreens/common (4.19.0):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
- fast_float
|
||||
@@ -2665,6 +2588,7 @@ PODS:
|
||||
- React-jsi
|
||||
- React-NativeModulesApple
|
||||
- React-RCTFabric
|
||||
- React-RCTImage
|
||||
- React-renderercss
|
||||
- React-rendererdebug
|
||||
- React-utils
|
||||
@@ -2674,21 +2598,6 @@ PODS:
|
||||
- SocketRocket
|
||||
- Yoga
|
||||
- SocketRocket (0.7.1)
|
||||
- vision-camera-face-detector (0.1.8):
|
||||
- GoogleMLKit/FaceDetection
|
||||
- React-Core
|
||||
- VisionCamera (4.7.3):
|
||||
- VisionCamera/Core (= 4.7.3)
|
||||
- VisionCamera/FrameProcessors (= 4.7.3)
|
||||
- VisionCamera/React (= 4.7.3)
|
||||
- VisionCamera/Core (4.7.3)
|
||||
- VisionCamera/FrameProcessors (4.7.3):
|
||||
- React
|
||||
- React-callinvoker
|
||||
- react-native-worklets-core
|
||||
- VisionCamera/React (4.7.3):
|
||||
- React-Core
|
||||
- VisionCamera/FrameProcessors
|
||||
- Yoga (0.0.0)
|
||||
|
||||
DEPENDENCIES:
|
||||
@@ -2738,8 +2647,6 @@ DEPENDENCIES:
|
||||
- React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)
|
||||
- react-native-biometrics (from `../node_modules/react-native-biometrics`)
|
||||
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
|
||||
- "react-native-vector-icons-ionicons (from `../node_modules/@react-native-vector-icons/ionicons`)"
|
||||
- react-native-worklets-core (from `../node_modules/react-native-worklets-core`)
|
||||
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
|
||||
- React-networking (from `../node_modules/react-native/ReactCommon/react/networking`)
|
||||
- React-oscompat (from `../node_modules/react-native/ReactCommon/oscompat`)
|
||||
@@ -2773,27 +2680,12 @@ DEPENDENCIES:
|
||||
- ReactAppDependencyProvider (from `build/generated/ios/ReactAppDependencyProvider`)
|
||||
- ReactCodegen (from `build/generated/ios/ReactCodegen`)
|
||||
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
|
||||
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
|
||||
- RNKeychain (from `../node_modules/react-native-keychain`)
|
||||
- RNScreens (from `../node_modules/react-native-screens`)
|
||||
- SocketRocket (~> 0.7.1)
|
||||
- vision-camera-face-detector (from `../node_modules/vision-camera-face-detector`)
|
||||
- VisionCamera (from `../node_modules/react-native-vision-camera`)
|
||||
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- GoogleDataTransport
|
||||
- GoogleMLKit
|
||||
- GoogleToolboxForMac
|
||||
- GoogleUtilities
|
||||
- GoogleUtilitiesComponents
|
||||
- GTMSessionFetcher
|
||||
- MLImage
|
||||
- MLKitCommon
|
||||
- MLKitFaceDetection
|
||||
- MLKitVision
|
||||
- nanopb
|
||||
- PromisesObjC
|
||||
- SocketRocket
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
@@ -2888,10 +2780,6 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native-biometrics"
|
||||
react-native-safe-area-context:
|
||||
:path: "../node_modules/react-native-safe-area-context"
|
||||
react-native-vector-icons-ionicons:
|
||||
:path: "../node_modules/@react-native-vector-icons/ionicons"
|
||||
react-native-worklets-core:
|
||||
:path: "../node_modules/react-native-worklets-core"
|
||||
React-NativeModulesApple:
|
||||
:path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios"
|
||||
React-networking:
|
||||
@@ -2958,14 +2846,8 @@ EXTERNAL SOURCES:
|
||||
:path: build/generated/ios/ReactCodegen
|
||||
ReactCommon:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
RNCAsyncStorage:
|
||||
:path: "../node_modules/@react-native-async-storage/async-storage"
|
||||
RNKeychain:
|
||||
:path: "../node_modules/react-native-keychain"
|
||||
vision-camera-face-detector:
|
||||
:path: "../node_modules/vision-camera-face-detector"
|
||||
VisionCamera:
|
||||
:path: "../node_modules/react-native-vision-camera"
|
||||
RNScreens:
|
||||
:path: "../node_modules/react-native-screens"
|
||||
Yoga:
|
||||
:path: "../node_modules/react-native/ReactCommon/yoga"
|
||||
|
||||
@@ -2976,19 +2858,7 @@ SPEC CHECKSUMS:
|
||||
FBLazyVector: 309703e71d3f2f1ed7dc7889d58309c9d77a95a4
|
||||
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
|
||||
glog: 5683914934d5b6e4240e497e0f4a3b42d1854183
|
||||
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
|
||||
GoogleMLKit: 97ac7af399057e99182ee8edfa8249e3226a4065
|
||||
GoogleToolboxForMac: d1a2cbf009c453f4d6ded37c105e2f67a32206d8
|
||||
GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15
|
||||
GoogleUtilitiesComponents: 679b2c881db3b615a2777504623df6122dd20afe
|
||||
GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6
|
||||
hermes-engine: e32c23b48a7e7bba5949724df09e91da62deb39d
|
||||
MLImage: 1824212150da33ef225fbd3dc49f184cf611046c
|
||||
MLKitCommon: afec63980417d29ffbb4790529a1b0a2291699e1
|
||||
MLKitFaceDetection: 7c0e8bf09ddd27105da32d088fca978a99fc30cc
|
||||
MLKitVision: e858c5f125ecc288e4a31127928301eaba9ae0c1
|
||||
nanopb: 438bc412db1928dac798aa6fd75726007be04262
|
||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||
hermes-engine: 02f0fb2d6d796f649e798ca7ddeb82356ec34dd1
|
||||
RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669
|
||||
RCTDeprecation: a41bbdd9af30bf2e5715796b313e44ec43eefff1
|
||||
RCTRequired: 7be34aabb0b77c3cefe644528df0fa0afad4e4d0
|
||||
@@ -3027,8 +2897,6 @@ SPEC CHECKSUMS:
|
||||
React-microtasksnativemodule: cdc02da075f2857803ed63f24f5f72fc40e094c0
|
||||
react-native-biometrics: 43ed5b828646a7862dbc7945556446be00798e7d
|
||||
react-native-safe-area-context: c00143b4823773bba23f2f19f85663ae89ceb460
|
||||
react-native-vector-icons-ionicons: ad07e944a092a5cf71b8b569d8f5ce2bf674c415
|
||||
react-native-worklets-core: 28a6e2121dcf62543b703e81bc4860e9a0150cee
|
||||
React-NativeModulesApple: a2c3d2cbec893956a5b3e4060322db2984fff75b
|
||||
React-networking: 3f98bd96893a294376e7e03730947a08d474c380
|
||||
React-oscompat: 80166b66da22e7af7fad94474e9997bd52d4c8c6
|
||||
@@ -3062,13 +2930,10 @@ SPEC CHECKSUMS:
|
||||
ReactAppDependencyProvider: 0eb286cc274abb059ee601b862ebddac2e681d01
|
||||
ReactCodegen: 3d48510bcef445f6403c0004047d4d9cbb915435
|
||||
ReactCommon: ac934cb340aee91282ecd6f273a26d24d4c55cae
|
||||
RNCAsyncStorage: 29f0230e1a25f36c20b05f65e2eb8958d6526e82
|
||||
RNKeychain: a2c134ab796272c3d605e035ab727591000b30f3
|
||||
RNScreens: ffbb0296608eb3560de641a711bbdb663ed1f6b4
|
||||
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
|
||||
vision-camera-face-detector: 121594b24889f2996de6cb233f6965e7900952cc
|
||||
VisionCamera: 0044a94f7489f19e19d5938e97dfc36f4784af3c
|
||||
Yoga: 5456bb010373068fc92221140921b09d126b116e
|
||||
|
||||
PODFILE CHECKSUM: e0882a7b99dc9c0e8d75aefd548a7e1553fa08f6
|
||||
PODFILE CHECKSUM: 34da44c2d7e6f9ba1a69997d2e260ac69ce9dff3
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
@@ -7,23 +7,23 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0C80B921A6F3F58F76C31292 /* libPods-authenticationsdk.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-authenticationsdk.a */; };
|
||||
0C80B921A6F3F58F76C31292 /* libPods-RNAuthentication.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-RNAuthentication.a */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; };
|
||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
|
||||
AC40AE863A1BE7BA9152BD0A /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
|
||||
FDE86AD04E2D8E32DF80DF88 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
13B07F961A680F5B00A75B9A /* authenticationsdk.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = authenticationsdk.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = authenticationsdk/Images.xcassets; sourceTree = "<group>"; };
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = authenticationsdk/Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = authenticationsdk/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
3B4392A12AC88292D35C810B /* Pods-authenticationsdk.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-authenticationsdk.debug.xcconfig"; path = "Target Support Files/Pods-authenticationsdk/Pods-authenticationsdk.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
5709B34CF0A7D63546082F79 /* Pods-authenticationsdk.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-authenticationsdk.release.xcconfig"; path = "Target Support Files/Pods-authenticationsdk/Pods-authenticationsdk.release.xcconfig"; sourceTree = "<group>"; };
|
||||
5DCACB8F33CDC322A6C60F78 /* libPods-authenticationsdk.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-authenticationsdk.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = authenticationsdk/AppDelegate.swift; sourceTree = "<group>"; };
|
||||
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = authenticationsdk/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* RNAuthentication.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RNAuthentication.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = RNAuthentication/Images.xcassets; sourceTree = "<group>"; };
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RNAuthentication/Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = RNAuthentication/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
3B4392A12AC88292D35C810B /* Pods-RNAuthentication.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNAuthentication.debug.xcconfig"; path = "Target Support Files/Pods-RNAuthentication/Pods-RNAuthentication.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
5709B34CF0A7D63546082F79 /* Pods-RNAuthentication.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNAuthentication.release.xcconfig"; path = "Target Support Files/Pods-RNAuthentication/Pods-RNAuthentication.release.xcconfig"; sourceTree = "<group>"; };
|
||||
5DCACB8F33CDC322A6C60F78 /* libPods-RNAuthentication.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNAuthentication.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = RNAuthentication/AppDelegate.swift; sourceTree = "<group>"; };
|
||||
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = RNAuthentication/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@@ -32,14 +32,14 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0C80B921A6F3F58F76C31292 /* libPods-authenticationsdk.a in Frameworks */,
|
||||
0C80B921A6F3F58F76C31292 /* libPods-RNAuthentication.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
13B07FAE1A68108700A75B9A /* authenticationsdk */ = {
|
||||
13B07FAE1A68108700A75B9A /* RNAuthentication */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||
@@ -48,14 +48,14 @@
|
||||
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
|
||||
13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */,
|
||||
);
|
||||
name = authenticationsdk;
|
||||
name = RNAuthentication;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
||||
5DCACB8F33CDC322A6C60F78 /* libPods-authenticationsdk.a */,
|
||||
5DCACB8F33CDC322A6C60F78 /* libPods-RNAuthentication.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@@ -70,7 +70,7 @@
|
||||
83CBB9F61A601CBA00E9B192 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAE1A68108700A75B9A /* authenticationsdk */,
|
||||
13B07FAE1A68108700A75B9A /* RNAuthentication */,
|
||||
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
2D16E6871FA4F8E400B85C8A /* Frameworks */,
|
||||
@@ -84,7 +84,7 @@
|
||||
83CBBA001A601CBA00E9B192 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07F961A680F5B00A75B9A /* authenticationsdk.app */,
|
||||
13B07F961A680F5B00A75B9A /* RNAuthentication.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -92,8 +92,8 @@
|
||||
BBD78D7AC51CEA395F1C20DB /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3B4392A12AC88292D35C810B /* Pods-authenticationsdk.debug.xcconfig */,
|
||||
5709B34CF0A7D63546082F79 /* Pods-authenticationsdk.release.xcconfig */,
|
||||
3B4392A12AC88292D35C810B /* Pods-RNAuthentication.debug.xcconfig */,
|
||||
5709B34CF0A7D63546082F79 /* Pods-RNAuthentication.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
@@ -101,9 +101,9 @@
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
13B07F861A680F5B00A75B9A /* authenticationsdk */ = {
|
||||
13B07F861A680F5B00A75B9A /* RNAuthentication */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "authenticationsdk" */;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "RNAuthentication" */;
|
||||
buildPhases = (
|
||||
C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */,
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
@@ -117,9 +117,9 @@
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = authenticationsdk;
|
||||
productName = authenticationsdk;
|
||||
productReference = 13B07F961A680F5B00A75B9A /* authenticationsdk.app */;
|
||||
name = RNAuthentication;
|
||||
productName = RNAuthentication;
|
||||
productReference = 13B07F961A680F5B00A75B9A /* RNAuthentication.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
@@ -135,7 +135,7 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "authenticationsdk" */;
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "RNAuthentication" */;
|
||||
compatibilityVersion = "Xcode 12.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
@@ -148,7 +148,7 @@
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
13B07F861A680F5B00A75B9A /* authenticationsdk */,
|
||||
13B07F861A680F5B00A75B9A /* RNAuthentication */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -160,7 +160,7 @@
|
||||
files = (
|
||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
AC40AE863A1BE7BA9152BD0A /* PrivacyInfo.xcprivacy in Resources */,
|
||||
FDE86AD04E2D8E32DF80DF88 /* PrivacyInfo.xcprivacy in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -189,15 +189,15 @@
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-authenticationsdk/Pods-authenticationsdk-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-RNAuthentication/Pods-RNAuthentication-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-authenticationsdk/Pods-authenticationsdk-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-RNAuthentication/Pods-RNAuthentication-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-authenticationsdk/Pods-authenticationsdk-frameworks.sh\"\n";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNAuthentication/Pods-RNAuthentication-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = {
|
||||
@@ -215,7 +215,7 @@
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-authenticationsdk-checkManifestLockResult.txt",
|
||||
"$(DERIVED_FILE_DIR)/Pods-RNAuthentication-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
@@ -228,15 +228,15 @@
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-authenticationsdk/Pods-authenticationsdk-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-RNAuthentication/Pods-RNAuthentication-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-authenticationsdk/Pods-authenticationsdk-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-RNAuthentication/Pods-RNAuthentication-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-authenticationsdk/Pods-authenticationsdk-resources.sh\"\n";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNAuthentication/Pods-RNAuthentication-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
@@ -255,13 +255,13 @@
|
||||
/* Begin XCBuildConfiguration section */
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-authenticationsdk.debug.xcconfig */;
|
||||
baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-RNAuthentication.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = authenticationsdk/Info.plist;
|
||||
INFOPLIST_FILE = RNAuthentication/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -274,7 +274,7 @@
|
||||
"-lc++",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = authenticationsdk;
|
||||
PRODUCT_NAME = RNAuthentication;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
@@ -283,12 +283,12 @@
|
||||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-authenticationsdk.release.xcconfig */;
|
||||
baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-RNAuthentication.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
INFOPLIST_FILE = authenticationsdk/Info.plist;
|
||||
INFOPLIST_FILE = RNAuthentication/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -301,7 +301,7 @@
|
||||
"-lc++",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = authenticationsdk;
|
||||
PRODUCT_NAME = RNAuthentication;
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
@@ -456,7 +456,7 @@
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "authenticationsdk" */ = {
|
||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "RNAuthentication" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
13B07F941A680F5B00A75B9A /* Debug */,
|
||||
@@ -465,7 +465,7 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "authenticationsdk" */ = {
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "RNAuthentication" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
83CBBA201A601CBA00E9B192 /* Debug */,
|
||||
@@ -15,9 +15,9 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "authenticationsdk.app"
|
||||
BlueprintName = "authenticationsdk"
|
||||
ReferencedContainer = "container:authenticationsdk.xcodeproj">
|
||||
BuildableName = "RNAuthentication.app"
|
||||
BlueprintName = "RNAuthentication"
|
||||
ReferencedContainer = "container:RNAuthentication.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
@@ -33,9 +33,9 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
|
||||
BuildableName = "authenticationsdkTests.xctest"
|
||||
BlueprintName = "authenticationsdkTests"
|
||||
ReferencedContainer = "container:authenticationsdk.xcodeproj">
|
||||
BuildableName = "RNAuthenticationTests.xctest"
|
||||
BlueprintName = "RNAuthenticationTests"
|
||||
ReferencedContainer = "container:RNAuthentication.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
@@ -55,9 +55,9 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "authenticationsdk.app"
|
||||
BlueprintName = "authenticationsdk"
|
||||
ReferencedContainer = "container:authenticationsdk.xcodeproj">
|
||||
BuildableName = "RNAuthentication.app"
|
||||
BlueprintName = "RNAuthentication"
|
||||
ReferencedContainer = "container:RNAuthentication.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
@@ -72,9 +72,9 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "authenticationsdk.app"
|
||||
BlueprintName = "authenticationsdk"
|
||||
ReferencedContainer = "container:authenticationsdk.xcodeproj">
|
||||
BuildableName = "RNAuthentication.app"
|
||||
BlueprintName = "RNAuthentication"
|
||||
ReferencedContainer = "container:RNAuthentication.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
@@ -2,7 +2,7 @@
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:authenticationsdk.xcodeproj">
|
||||
location = "group:RNAuthentication.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
@@ -24,7 +24,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
window = UIWindow(frame: UIScreen.main.bounds)
|
||||
|
||||
factory.startReactNative(
|
||||
withModuleName: "authenticationsdk",
|
||||
withModuleName: "RNAuthentication",
|
||||
in: window,
|
||||
launchOptions: launchOptions
|
||||
)
|
||||
@@ -7,7 +7,7 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>authenticationsdk</string>
|
||||
<string>RNAuthentication</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
@@ -35,8 +35,6 @@
|
||||
</dict>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string></string>
|
||||
<key>NSFaceIDUsageDescription</key>
|
||||
<string>This app uses Face ID to secure access to sensitive features.</string>
|
||||
<key>RCTNewArchEnabled</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
@@ -16,7 +16,7 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="authenticationsdk" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="GJd-Yh-RWb">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="RNAuthentication" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="GJd-Yh-RWb">
|
||||
<rect key="frame" x="0.0" y="202" width="375" height="43"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@@ -4,16 +4,6 @@
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>CA92.1</string>
|
||||
<string>1C8F.1</string>
|
||||
<string>C56D.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
||||
@@ -22,6 +12,14 @@
|
||||
<string>C617.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>CA92.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
|
||||
1523
package-lock.json
generated
1523
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
19
package.json
19
package.json
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "authenticationsdk",
|
||||
"name": "RNAuthentication",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@@ -7,20 +7,21 @@
|
||||
"ios": "react-native run-ios",
|
||||
"lint": "eslint .",
|
||||
"start": "react-native start",
|
||||
"test": "jest"
|
||||
"test": "jest",
|
||||
"postinstall": "patch-package"
|
||||
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-native-async-storage/async-storage": "^2.2.0",
|
||||
"@react-native-vector-icons/ionicons": "^12.3.0",
|
||||
"@react-native/new-app-screen": "0.83.1",
|
||||
"@react-navigation/native": "^7.1.27",
|
||||
"@react-navigation/native-stack": "^7.9.1",
|
||||
"install": "^0.13.0",
|
||||
"react": "19.2.0",
|
||||
"react-native": "0.83.1",
|
||||
"react-native-biometric-check": "^1.0.1",
|
||||
"react-native-biometrics": "^3.0.1",
|
||||
"react-native-keychain": "^10.0.0",
|
||||
"react-native-safe-area-context": "^5.5.2",
|
||||
"react-native-vision-camera": "^4.7.3",
|
||||
"react-native-worklets-core": "^1.6.2",
|
||||
"vision-camera-face-detector": "^0.1.8"
|
||||
"react-native-screens": "^4.19.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
@@ -38,6 +39,8 @@
|
||||
"@types/react-test-renderer": "^19.1.0",
|
||||
"eslint": "^8.19.0",
|
||||
"jest": "^29.6.3",
|
||||
"patch-package": "^8.0.1",
|
||||
"postinstall-postinstall": "^2.1.0",
|
||||
"prettier": "2.8.8",
|
||||
"react-test-renderer": "19.2.0",
|
||||
"typescript": "^5.8.3"
|
||||
|
||||
56
patches/react-native-biometrics+3.0.1.patch
Normal file
56
patches/react-native-biometrics+3.0.1.patch
Normal file
@@ -0,0 +1,56 @@
|
||||
diff --git a/node_modules/react-native-biometrics/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java b/node_modules/react-native-biometrics/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java
|
||||
index 624ecd9..d135072 100644
|
||||
--- a/node_modules/react-native-biometrics/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java
|
||||
+++ b/node_modules/react-native-biometrics/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java
|
||||
@@ -182,24 +182,38 @@ public class ReactNativeBiometrics extends ReactContextBaseJavaModule {
|
||||
}
|
||||
}
|
||||
|
||||
- private PromptInfo getPromptInfo(String promptMessage, String cancelButtonText, boolean allowDeviceCredentials) {
|
||||
- PromptInfo.Builder builder = new PromptInfo.Builder().setTitle(promptMessage);
|
||||
+ private BiometricPrompt.PromptInfo getPromptInfo(
|
||||
+ String promptMessage,
|
||||
+ String cancelButtonText,
|
||||
+ boolean allowDeviceCredentials
|
||||
+) {
|
||||
+ BiometricPrompt.PromptInfo.Builder builder =
|
||||
+ new BiometricPrompt.PromptInfo.Builder()
|
||||
+ .setTitle(promptMessage);
|
||||
+
|
||||
+ builder.setAllowedAuthenticators(
|
||||
+ getAllowedAuthenticators(allowDeviceCredentials)
|
||||
+ );
|
||||
+
|
||||
+ if (!allowDeviceCredentials || isCurrentSDK29OrEarlier()) {
|
||||
+ builder.setNegativeButtonText(cancelButtonText);
|
||||
+ }
|
||||
|
||||
- builder.setAllowedAuthenticators(getAllowedAuthenticators(allowDeviceCredentials));
|
||||
+ return builder.build();
|
||||
+}
|
||||
|
||||
- if (allowDeviceCredentials == false || isCurrentSDK29OrEarlier()) {
|
||||
- builder.setNegativeButtonText(cancelButtonText);
|
||||
- }
|
||||
+private int getAllowedAuthenticators(boolean allowDeviceCredentials) {
|
||||
+ int authenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK;
|
||||
|
||||
- return builder.build();
|
||||
+ if (allowDeviceCredentials) {
|
||||
+ authenticators |= BiometricManager.Authenticators.DEVICE_CREDENTIAL;
|
||||
}
|
||||
|
||||
- private int getAllowedAuthenticators(boolean allowDeviceCredentials) {
|
||||
- if (allowDeviceCredentials && !isCurrentSDK29OrEarlier()) {
|
||||
- return BiometricManager.Authenticators.BIOMETRIC_STRONG | BiometricManager.Authenticators.DEVICE_CREDENTIAL;
|
||||
- }
|
||||
- return BiometricManager.Authenticators.BIOMETRIC_STRONG;
|
||||
- }
|
||||
+ return authenticators;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
|
||||
private boolean isCurrentSDK29OrEarlier() {
|
||||
return Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q;
|
||||
@@ -1,79 +0,0 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { View, Text, Alert } from "react-native";
|
||||
import { Camera, useCameraDevices } from "react-native-vision-camera";
|
||||
import { useFaceDetector } from "vision-camera-face-detector";
|
||||
import * as Keychain from "react-native-keychain";
|
||||
|
||||
export default function FaceRecognition() {
|
||||
const [authenticated, setAuthenticated] = useState(false);
|
||||
const devices = useCameraDevices();
|
||||
const device = devices.front;
|
||||
|
||||
useEffect(() => {
|
||||
Camera.requestCameraPermission();
|
||||
authenticateWithKeychain();
|
||||
}, []);
|
||||
|
||||
async function authenticateWithKeychain() {
|
||||
try {
|
||||
// Try to retrieve a protected generic password which will trigger
|
||||
// the system authentication prompt (Face ID / Touch ID / passcode).
|
||||
const creds = await Keychain.getGenericPassword({
|
||||
authenticationPrompt: { title: "Authenticate to unlock" },
|
||||
});
|
||||
|
||||
if (creds) {
|
||||
setAuthenticated(true);
|
||||
console.log("Authenticated via Keychain, credentials found.");
|
||||
return;
|
||||
}
|
||||
|
||||
// If no credentials stored yet, create one protected by biometrics
|
||||
await Keychain.setGenericPassword("user", "secure-token", {
|
||||
accessControl: Keychain.ACCESS_CONTROL.BIOMETRY_ANY,
|
||||
accessible: Keychain.ACCESSIBLE.WHEN_PASSCODE_SET_THIS_DEVICE_ONLY,
|
||||
});
|
||||
|
||||
// Now request access which will prompt biometric/passcode
|
||||
const creds2 = await Keychain.getGenericPassword({
|
||||
authenticationPrompt: { title: "Authenticate to unlock" },
|
||||
});
|
||||
|
||||
if (creds2) {
|
||||
setAuthenticated(true);
|
||||
console.log("Authenticated after storing credentials.");
|
||||
}
|
||||
} catch (e: any) {
|
||||
console.log("Authentication error:", e);
|
||||
Alert.alert("Authentication failed", e?.message || String(e));
|
||||
}
|
||||
}
|
||||
|
||||
const faceDetector = useFaceDetector({
|
||||
landmarkMode: "all",
|
||||
performanceMode: "fast",
|
||||
});
|
||||
|
||||
if (!device) return <Text>Loading camera...</Text>;
|
||||
|
||||
if (!authenticated)
|
||||
return (
|
||||
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
|
||||
<Text>Locked. Please authenticate to continue.</Text>
|
||||
</View>
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1 }}>
|
||||
<Camera
|
||||
style={{ flex: 1 }}
|
||||
device={device}
|
||||
isActive={true}
|
||||
faceDetector={faceDetector}
|
||||
faceDetectionCallback={(faces) => {
|
||||
console.log("Faces:", faces);
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
TextInput,
|
||||
Button,
|
||||
Alert,
|
||||
StyleSheet,
|
||||
} from 'react-native';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
|
||||
const PIN_KEY = 'USER_PIN';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [pin, setPin] = useState<string>('');
|
||||
const [savedPin, setSavedPin] = useState<string | null>(null);
|
||||
const [loggedIn, setLoggedIn] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
loadPin();
|
||||
}, []);
|
||||
|
||||
const loadPin = async (): Promise<void> => {
|
||||
const storedPin = await AsyncStorage.getItem(PIN_KEY);
|
||||
setSavedPin(storedPin);
|
||||
};
|
||||
|
||||
const setUserPin = async (): Promise<void> => {
|
||||
if (pin.length !== 4) {
|
||||
Alert.alert('PIN must be 4 digits');
|
||||
return;
|
||||
}
|
||||
await AsyncStorage.setItem(PIN_KEY, pin);
|
||||
setSavedPin(pin);
|
||||
setPin('');
|
||||
Alert.alert('PIN set successfully');
|
||||
};
|
||||
|
||||
const loginWithPin = (): void => {
|
||||
if (pin === savedPin) {
|
||||
setLoggedIn(true);
|
||||
setPin('');
|
||||
} else {
|
||||
Alert.alert('Incorrect PIN');
|
||||
}
|
||||
};
|
||||
|
||||
const logout = (): void => {
|
||||
setLoggedIn(false);
|
||||
};
|
||||
|
||||
if (loggedIn) {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>Hi Dude!</Text>
|
||||
<Button title="Logout" onPress={logout} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>
|
||||
{savedPin ? 'Enter PIN' : 'Set PIN'}
|
||||
</Text>
|
||||
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
keyboardType="numeric"
|
||||
secureTextEntry
|
||||
maxLength={4}
|
||||
value={pin}
|
||||
onChangeText={setPin}
|
||||
placeholder="Enter 4-digit PIN"
|
||||
/>
|
||||
|
||||
<Button
|
||||
title={savedPin ? 'Login' : 'Save PIN'}
|
||||
onPress={savedPin ? loginWithPin : setUserPin}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
padding: 20,
|
||||
},
|
||||
title: {
|
||||
fontSize: 22,
|
||||
marginBottom: 20,
|
||||
textAlign: 'center',
|
||||
},
|
||||
input: {
|
||||
borderWidth: 1,
|
||||
padding: 12,
|
||||
marginBottom: 20,
|
||||
borderRadius: 5,
|
||||
fontSize: 18,
|
||||
textAlign: 'center',
|
||||
},
|
||||
});
|
||||
@@ -1,70 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
TextInput,
|
||||
Alert,
|
||||
} from 'react-native';
|
||||
import { verifyPin } from './authorised/AppPinService';
|
||||
import { unlockWithDevice, unlockApp } from './authorised/AuthManager';
|
||||
|
||||
const LockScreen = ({ onUnlock }: any) => {
|
||||
const [pin, setPin] = useState('');
|
||||
|
||||
const handlePinUnlock = async () => {
|
||||
const valid = await verifyPin(pin);
|
||||
if (valid) {
|
||||
await unlockApp();
|
||||
onUnlock();
|
||||
} else {
|
||||
Alert.alert('Wrong PIN');
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeviceUnlock = async () => {
|
||||
const res = await unlockWithDevice();
|
||||
if (res.success) {
|
||||
await unlockApp();
|
||||
onUnlock();
|
||||
} else {
|
||||
Alert.alert('Authentication Failed');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, justifyContent: 'center', padding: 20 }}>
|
||||
<Text style={{ fontSize: 20, marginBottom: 10 }}>
|
||||
Enter App PIN
|
||||
</Text>
|
||||
|
||||
<TextInput
|
||||
keyboardType="number-pad"
|
||||
secureTextEntry
|
||||
maxLength={4}
|
||||
value={pin}
|
||||
onChangeText={setPin}
|
||||
style={{
|
||||
borderWidth: 1,
|
||||
padding: 12,
|
||||
borderRadius: 6,
|
||||
marginBottom: 10,
|
||||
}}
|
||||
/>
|
||||
|
||||
<TouchableOpacity onPress={handlePinUnlock}>
|
||||
<Text style={{ color: 'blue', marginBottom: 20 }}>
|
||||
Unlock with PIN
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity onPress={handleDeviceUnlock}>
|
||||
<Text style={{ color: 'green' }}>
|
||||
Unlock with Device Lock
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default LockScreen;
|
||||
@@ -1,38 +0,0 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { AppState, View, Text } from 'react-native';
|
||||
import { isPinSet } from './authorised/AppPinService';
|
||||
import { isAppLocked, lockApp } from './authorised/AuthManager';
|
||||
import SetPinScreen from './SetPinScreen';
|
||||
import LockScreen from './LockScreen';
|
||||
|
||||
const App = () => {
|
||||
const [locked, setLocked] = useState(true);
|
||||
const [pinExists, setPinExists] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
isPinSet().then(setPinExists);
|
||||
isAppLocked().then(setLocked);
|
||||
|
||||
const sub = AppState.addEventListener('change', state => {
|
||||
if (state !== 'active') lockApp();
|
||||
});
|
||||
|
||||
return () => sub.remove();
|
||||
}, []);
|
||||
|
||||
if (!pinExists) {
|
||||
return <SetPinScreen onDone={() => setPinExists(true)} />;
|
||||
}
|
||||
|
||||
if (locked) {
|
||||
return <LockScreen onUnlock={() => setLocked(false)} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
||||
<Text>🔓 App Unlocked (Home Screen)</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
@@ -1,20 +0,0 @@
|
||||
import * as Keychain from 'react-native-keychain';
|
||||
|
||||
const PIN_KEY = 'APP_PIN';
|
||||
|
||||
export const savePin = async (pin: string) => {
|
||||
await Keychain.setGenericPassword(PIN_KEY, pin, {
|
||||
accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED,
|
||||
});
|
||||
};
|
||||
|
||||
export const verifyPin = async (inputPin: string) => {
|
||||
const creds = await Keychain.getGenericPassword();
|
||||
if (!creds) return false;
|
||||
return creds.password === inputPin;
|
||||
};
|
||||
|
||||
export const isPinSet = async () => {
|
||||
const creds = await Keychain.getGenericPassword();
|
||||
return !!creds;
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import { authenticateWithDeviceLock } from './deviceAuth';
|
||||
|
||||
const LOCK_KEY = 'APP_LOCKED';
|
||||
|
||||
export const lockApp = async () => {
|
||||
await AsyncStorage.setItem(LOCK_KEY, 'true');
|
||||
};
|
||||
|
||||
export const unlockApp = async () => {
|
||||
await AsyncStorage.removeItem(LOCK_KEY);
|
||||
};
|
||||
|
||||
export const isAppLocked = async () => {
|
||||
const v = await AsyncStorage.getItem(LOCK_KEY);
|
||||
return v === 'true';
|
||||
};
|
||||
|
||||
export const unlockWithDevice = async () => {
|
||||
return await authenticateWithDeviceLock();
|
||||
};
|
||||
@@ -1,35 +0,0 @@
|
||||
import React from 'react';
|
||||
import { View, Text, TouchableOpacity, Alert } from 'react-native';
|
||||
import { authenticateWithDeviceLock } from './deviceAuth';
|
||||
|
||||
const AuthScreen = () => {
|
||||
const handleAuth = async () => {
|
||||
const result = await authenticateWithDeviceLock();
|
||||
|
||||
if (result.success) {
|
||||
Alert.alert('Success', 'User authenticated');
|
||||
// 👉 Navigate to Home / Unlock app
|
||||
} else {
|
||||
Alert.alert('Failed', result.message);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
||||
<TouchableOpacity
|
||||
onPress={handleAuth}
|
||||
style={{
|
||||
backgroundColor: '#000',
|
||||
padding: 15,
|
||||
borderRadius: 8,
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: '#fff', fontSize: 16 }}>
|
||||
Unlock with Device Lock
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default AuthScreen;
|
||||
@@ -1,40 +0,0 @@
|
||||
import ReactNativeBiometrics from 'react-native-biometrics';
|
||||
|
||||
const rnBiometrics = new ReactNativeBiometrics({
|
||||
allowDeviceCredentials: true, // 👈 IMPORTANT (PIN / Pattern)
|
||||
});
|
||||
|
||||
export const authenticateWithDeviceLock = async () => {
|
||||
try {
|
||||
const { available } = await rnBiometrics.isSensorAvailable();
|
||||
|
||||
if (!available) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Device lock is not available',
|
||||
};
|
||||
}
|
||||
|
||||
const result = await rnBiometrics.simplePrompt({
|
||||
promptMessage: 'Authenticate to continue',
|
||||
cancelButtonText: 'Cancel',
|
||||
});
|
||||
|
||||
if (result.success) {
|
||||
return {
|
||||
success: true,
|
||||
message: 'Authentication successful',
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Authentication cancelled',
|
||||
};
|
||||
}
|
||||
} catch (error: any) {
|
||||
return {
|
||||
success: false,
|
||||
message: error?.message || 'Authentication failed',
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -2,6 +2,7 @@
|
||||
"extends": "@react-native/typescript-config",
|
||||
"compilerOptions": {
|
||||
"types": ["jest"],
|
||||
"jsx":"react-native"
|
||||
},
|
||||
"include": ["**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["**/node_modules", "**/Pods"]
|
||||
|
||||
Reference in New Issue
Block a user