From 9d6dd020d608a2c23862bfd754f817a35170d0eb Mon Sep 17 00:00:00 2001 From: Anmol Verma Date: Sat, 31 Aug 2024 15:59:15 +0530 Subject: [PATCH 1/2] Add biometric authentication to authwrapper --- apps/expo/package.json | 1 + .../modules/auth/components/AuthWrapper.tsx | 62 ++++++++++++++++++- yarn.lock | 12 ++++ 3 files changed, 72 insertions(+), 3 deletions(-) diff --git a/apps/expo/package.json b/apps/expo/package.json index 8aeff5879..ac560ee71 100644 --- a/apps/expo/package.json +++ b/apps/expo/package.json @@ -102,6 +102,7 @@ "expo-image-picker": "~14.7.1", "expo-linear-gradient": "~12.7.2", "expo-linking": "~6.2.2", + "expo-local-authentication": "~13.8.0", "expo-location": "~16.5.5", "expo-random": "~13.6.0", "expo-router": "~3.4.10", diff --git a/packages/app/modules/auth/components/AuthWrapper.tsx b/packages/app/modules/auth/components/AuthWrapper.tsx index 32db97c46..eff9b79c4 100644 --- a/packages/app/modules/auth/components/AuthWrapper.tsx +++ b/packages/app/modules/auth/components/AuthWrapper.tsx @@ -1,9 +1,11 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { AuthLoader } from './AuthLoader'; import { Redirect } from 'app/components/Redirect'; -import { RSpinner, RText } from '@packrat/ui'; -import { Platform, View } from 'react-native'; +import { RSpinner, RText, RButton } from '@packrat/ui'; +import { Platform, View, Alert } from 'react-native'; import LandingPage from 'app/components/landing_page'; +import * as LocalAuthentication from 'expo-local-authentication'; +import useTheme from 'app/hooks/useTheme'; interface AuthWrapperProps { children?: React.ReactNode; @@ -14,6 +16,60 @@ export const AuthWrapper = ({ children, unauthorizedElement, }: AuthWrapperProps) => { + const [isAuthenticated, setIsAuthenticated] = useState(false); + const { currentTheme } = useTheme(); + + const authenticate = async () => { + const hasHardware = await LocalAuthentication.hasHardwareAsync(); + if (!hasHardware) { + Alert.alert( + 'Error', + 'Your device does not support biometric authentication.', + ); + return; + } + + const hasBiometrics = await LocalAuthentication.isEnrolledAsync(); + if (!hasBiometrics) { + Alert.alert( + 'Error', + 'No biometrics are enrolled. Please set up biometrics in your device settings.', + ); + return; + } + + const result = await LocalAuthentication.authenticateAsync({ + promptMessage: 'Authenticate to continue', + fallbackLabel: 'Use Passcode', + }); + + if (result.success) { + setIsAuthenticated(true); + } + }; + + useEffect(() => { + authenticate(); + }, []); + + if (!isAuthenticated) { + return ( + + + Please unlock to continue + + Unlock + + ); + } + const loadingElement = Platform.OS === 'web' ? ( Loading... diff --git a/yarn.lock b/yarn.lock index e6c794964..9ccf90679 100644 --- a/yarn.lock +++ b/yarn.lock @@ -20846,6 +20846,7 @@ __metadata: expo-image-picker: "npm:~14.7.1" expo-linear-gradient: "npm:~12.7.2" expo-linking: "npm:~6.2.2" + expo-local-authentication: "npm:~13.8.0" expo-location: "npm:~16.5.5" expo-random: "npm:~13.6.0" expo-router: "npm:~3.4.10" @@ -21162,6 +21163,17 @@ __metadata: languageName: node linkType: hard +"expo-local-authentication@npm:~13.8.0": + version: 13.8.0 + resolution: "expo-local-authentication@npm:13.8.0" + dependencies: + invariant: "npm:^2.2.4" + peerDependencies: + expo: "*" + checksum: 10/06ad68d96831058e51115fa398479faba9b4059564ecc44ee7eef739be7c5df1c632ec0138e008549dc2e7cd4a8eed9830d30ffb8ae97431e17f7ab8b2d55f87 + languageName: node + linkType: hard + "expo-location@npm:~16.5.5": version: 16.5.5 resolution: "expo-location@npm:16.5.5" From 37e25f216146eafc62292d313b91de355b06f297 Mon Sep 17 00:00:00 2001 From: Anmol Verma Date: Sun, 1 Sep 2024 09:58:46 +0530 Subject: [PATCH 2/2] Bypass authentication on web --- packages/app/modules/auth/components/AuthWrapper.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/app/modules/auth/components/AuthWrapper.tsx b/packages/app/modules/auth/components/AuthWrapper.tsx index eff9b79c4..5e2ff4875 100644 --- a/packages/app/modules/auth/components/AuthWrapper.tsx +++ b/packages/app/modules/auth/components/AuthWrapper.tsx @@ -20,6 +20,11 @@ export const AuthWrapper = ({ const { currentTheme } = useTheme(); const authenticate = async () => { + if (Platform.OS === 'web') { + setIsAuthenticated(true); + return; + } + const hasHardware = await LocalAuthentication.hasHardwareAsync(); if (!hasHardware) { Alert.alert(