Refactor and align App and POS auth logic

This commit is contained in:
minibits-cash
2026-01-28 14:03:53 +01:00
parent d80aefbc3e
commit f8019b3177
3 changed files with 74 additions and 19 deletions
+6 -17
View File
@@ -52,23 +52,12 @@ function App() {
// User authentication (biometrics / PIN)
if (userSettingsStore.isAuthOn) {
KeyChain.getOrCreateAuthToken(userSettingsStore.isAuthOn)
.then((authToken) => {
setIsUserAuthenticated(true)
log.trace('[App]', { authToken })
})
.catch((e: any) => {
log.warn('[App]', 'User authentication failed', { message: e.message })
if (e && typeof e === 'object') {
const errString = JSON.stringify(e)
const isBackPressed = errString.includes('code: 10')
const isCancellPressed = errString.includes('code: 13')
const isIOSCancel = 'code' in e && String(e.code) === '-128'
if (isCancellPressed || isBackPressed || isIOSCancel) {
RNExitApp.exitApp()
}
KeyChain.authenticateOnAppStart(userSettingsStore.isAuthOn)
.then((result) => {
if (result.success) {
setIsUserAuthenticated(true)
} else if (result.shouldExitApp) {
RNExitApp.exitApp()
}
})
} else {
+1 -1
View File
@@ -34,7 +34,7 @@ import RNExitApp from 'react-native-exit-app'
import { TransactionStatus } from '../models/Transaction'
import { maxTransactionsInHistory } from '../models/TransactionsStore'
import { StaticScreenProps, useNavigation } from '@react-navigation/native'
//
// refresh
type Props = StaticScreenProps<undefined>
+67 -1
View File
@@ -386,6 +386,53 @@ const removeAuthToken = async function (): Promise<boolean> {
export type AuthResult = {
success: boolean
shouldExitApp: boolean
}
/**
* Authenticate user on app start
* Creates auth token on first use, then requires biometric authentication
* Returns result object with success status and whether app should exit
*/
const authenticateOnAppStart = async function (isAuthOn: boolean): Promise<AuthResult> {
try {
const authToken = await getOrCreateAuthToken(isAuthOn)
if (authToken) {
log.trace('[authenticateOnAppStart]', 'App start authentication successful')
return { success: true, shouldExitApp: false }
}
log.trace('[authenticateOnAppStart]', 'No auth token found')
return { success: false, shouldExitApp: false }
} catch (e: any) {
// Handle specific error codes for user actions
if (e && typeof e === 'object') {
const errString = JSON.stringify(e)
const isBackPressed = errString.includes('code: 10')
const isCancelPressed = errString.includes('code: 13')
const isIOSCancel = 'code' in e && String(e.code) === '-128'
if (isBackPressed) {
log.trace('[authenticateOnAppStart]', 'User pressed back button')
return { success: false, shouldExitApp: true }
}
if (isCancelPressed || isIOSCancel) {
log.trace('[authenticateOnAppStart]', 'User cancelled authentication')
return { success: false, shouldExitApp: true }
}
}
log.warn('[authenticateOnAppStart]', 'Authentication failed', { message: e.message })
return { success: false, shouldExitApp: false }
}
}
async function updateAuthSettings(isAuthOn: boolean) {
log.trace('[updateAuthSettings] to', {isAuthOn})
@@ -426,7 +473,25 @@ const authenticatePOSMode = async function (): Promise<boolean> {
log.trace('[authenticatePOSMode]', 'No auth token found')
return false
} catch (e: any) {
log.trace('[authenticatePOSMode]', 'Authentication cancelled or failed', { message: e.message })
// Handle specific error codes for user actions
if (e && typeof e === 'object') {
const errString = JSON.stringify(e)
const isBackPressed = errString.includes('code: 10')
const isCancelPressed = errString.includes('code: 13')
const isIOSCancel = 'code' in e && String(e.code) === '-128'
if (isBackPressed) {
log.trace('[authenticatePOSMode]', 'User pressed back button')
return false
}
if (isCancelPressed || isIOSCancel) {
log.trace('[authenticatePOSMode]', 'User cancelled authentication')
return false
}
}
log.trace('[authenticatePOSMode]', 'Authentication failed', { message: e.message })
return false
}
}
@@ -526,6 +591,7 @@ export const KeyChain = {
getOrCreateAuthToken,
removeAuthToken,
updateAuthSettings,
authenticateOnAppStart,
authenticatePOSMode,
// server JWT tokens