An API client used for real work often holds sensitive production credentials — Bearer tokens, OAuth client secrets, API keys, and Basic Auth passwords. If a device is left unlocked or passed to another person, those secrets are one tap away. Xolo’s biometric lock addresses this by requiring Face ID, fingerprint, or another device-native biometric before the app becomes usable after it resumes from the background or restarts from a cold start.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/JonathanHerSa/xolo-api-hub/llms.txt
Use this file to discover all available pages before exploring further.
Enabling Biometric Lock
Navigate to Settings → Security and toggle Biometric Lock. Before enabling it, Xolo checks that the device actually supports biometric authentication by queryingBiometricService.isAvailable. If the device has no enrolled biometrics, the toggle remains disabled.
Once enabled, the lock state and its lock delay are persisted in flutter_secure_storage under the keys biometric_enabled and lock_delay, so the setting survives app restarts without touching the SQLite database.
You can also configure the lock delay — the number of seconds the app must be in the background before it locks on resume. The default delay is 30 seconds.
BiometricService
BiometricService is backed by the local_auth package and provides a minimal, safe API surface over the platform’s native biometric stack.
isAvailable
true if the device reports either canCheckBiometrics or isDeviceSupported(). Catches PlatformException and returns false so callers never need to handle platform errors themselves. On platforms where biometrics are unavailable (such as Linux desktop), this consistently returns false.
authenticate()
reason string (shown to the user as the unlock rationale). Returns true if the user successfully authenticates, false otherwise. If authentication is already in progress (_isAuthenticating == true), the method returns false immediately to prevent overlapping prompts. The persistAcrossBackgrounding flag is set to true so the prompt survives brief backgrounding.
cancelAuthentication()
LocalAuthentication.stopAuthentication() to dismiss any in-progress biometric prompt and resets the internal _isAuthenticating flag.
shouldLockApp()
true only when biometric lock is enabled, the device supports biometrics, and the time elapsed since markAppBackgrounded() was called meets or exceeds the configured lockDelay.
Biometric Lock Screen
When the app resumes from the background andBiometricService.shouldLockApp() returns true, the isAppLockedProvider state is set to true and Xolo overlays the entire UI with BiometricLockScreen.
BiometricLockScreen auto-triggers the system biometric prompt on mount (via initState) through an internal _bootstrap() call. If the device has become unavailable since the setting was last saved (e.g. the user removed their enrolled fingerprint), BiometricService.disableIfUnavailable() automatically turns off the lock and lets the user through. If biometric authentication fails, an error message is shown and a manual Unlock button allows the user to retry the prompt.
On a successful authentication, isAppLockedProvider is set to false and the lock screen is dismissed, returning the user to whatever screen they were on.
Biometric lock requires a device with enrolled biometrics. If no biometrics are enrolled, or if the device does not support hardware biometrics at all, the setting is automatically disabled and the lock screen will not appear. This check runs both when the setting is first toggled and every time the app attempts to lock.
Credential Storage
All authentication secrets managed by Xolo — Bearer tokens, OAuth 2.0 client secrets and access tokens, API key values, and Basic Auth passwords — are stored exclusively influtter_secure_storage. The shared instance is configured with AndroidOptions() so Android uses the Android Keystore backend.
SecurityService wraps this storage with three operations used by the rest of the codebase:
secure_auth_ref:) — never raw credentials. See the Auth Overview for details on how AuthSecretService manages this indirection.
Security Profiles
SecurityProfileService lets you choose one of three pre-defined security postures that control app-wide behaviour. The active profile is persisted via XoloRepository.setSetting() / getSetting() under the key security_profile.
| Profile | hideSensitiveValues | autoLockOnResume | Lock Delay | confirmBeforeExport |
|---|---|---|---|---|
standard | false | false | 30 s | false |
hardened | true | true | 15 s | true |
paranoid | true | true | 0 s | true |
hideSensitiveValues— whentrue, token and password fields in auth forms are always obscured, regardless of any individual field settings.autoLockOnResume— whentrue, the biometric lock overlay is shown every time the app returns from the background (subject to the lock delay).recommendedLockDelaySeconds— the suggested delay before locking;0means lock immediately on every resume.confirmBeforeExport— whentrue, Xolo shows a confirmation dialog before exporting any collection or environment data.
AES-256 Encryption
EncryptionService provides AES-256-CBC encryption for backup payloads exported from Xolo. It is independent of the biometric lock but forms part of the overall security story: even if a backup file is exfiltrated, its contents remain unreadable without the password.
Key derivation uses PBKDF2-HMAC-SHA256 with 120,000 rounds, a random 16-byte salt, and a 32-byte output key. Each encryption operation also generates a fresh 16-byte IV and appends a 32-byte HMAC-SHA256 tag to the payload for authenticated encryption (encrypt-then-MAC). The on-disk format is: