All resources
// Resources

Mobile Biometric Authentication: What to Verify

Published July 12, 2026

Biometric authentication is local user verification, not remote identity proof. Android and Apple keep biometric templates outside app access: app receives a success or failure result. That boundary matters. A green biometric prompt must not become permission to reuse an old server session, approve a different transaction, or silently reveal a protected secret.

This review asks a narrower question: what cryptographic operation becomes possible after local authentication, for how long, and through which fallback? OWASP MASVS identifies bypassable local authentication, weak fallback, missing step-up authentication, and missing invalidation after biometric enrollment as distinct failure classes.

Start with protected operation

Write one row per operation before reading code. “Use Face ID” is not a requirement; “sign this server challenge before changing a beneficiary” is.

OperationRequired local proofServer controlEvidence ownerPass condition
Open cached account datadevice credential may be acceptablevalid session still requiredmobile ownerapp cannot decrypt before prompt succeeds
Approve paymentstrong biometric, fresh promptserver verifies challenge, amount, recipient, expirypayment ownerchanged amount invalidates approval
Export recovery materialno local-only shortcutreauthentication and policy decisionidentity ownerfallback cannot weaken transaction policy

Keep challenge data scoped: include action, account, transaction identifier, expiry, and nonce. Never sign a generic “approved” string. Server must reject replayed, expired, or action-mismatched proof.

Bind prompt to key use

A visual prompt alone is weak evidence because an app can show it then use a previously available key or token. Bind authentication to the private-key operation or protected Keychain item. Android supports passing a CryptoObject to BiometricPrompt; generate a Keystore key requiring user authentication, then use its initialized cipher or signature only after prompt success. Example shape:

val spec = KeyGenParameterSpec.Builder(alias, PURPOSE_SIGN)
  .setUserAuthenticationRequired(true)
  .setUserAuthenticationParameters(0, AUTH_BIOMETRIC_STRONG)
  .setInvalidatedByBiometricEnrollment(true)
  .build()
// authenticate(promptInfo, BiometricPrompt.CryptoObject(signature))

0 means per-use authentication in this example. Check actual supported API levels and authenticator combinations; do not copy settings into a production policy without device testing. On iOS, LAContext evaluates a policy, while Keychain access control can require current biometry for a protected item. The secret or private key must remain protected by platform storage; do not replace this with an app-managed biometric flag.

Apple documents that LocalAuthentication returns a Boolean result and does not expose fingerprint or facial data. Android authenticator selection matters too: BIOMETRIC_STRONG and device credential are different policy choices. Choose them per operation, record reason, and test device support before release.

Fallback is policy, not error handling

Fallback happens when biometrics are unavailable, unenrolled, locked out, cancelled, or deliberately disabled. Device PIN/passcode can be a usable fallback for low-risk local unlock, but it changes assurance. A support PIN embedded in app UI, a remembered password, or “continue anyway” is not an equivalent fallback.

Define expected behavior for every outcome:

OutcomeExpected behaviorFail signalRemediation
biometric successperform bound operation onceoperation succeeds without bound objectrecreate protected key and retest
user cancelstop with no state changerequest proceeds after cancellationseparate cancel from success callback
lockout / unavailableoffer approved recovery or stopapp silently downgradesrequire explicit server reauthentication
device credential fallbackonly where risk owner approved ithigh-risk action accepts itremove fallback for that action
enrollment changedinvalidate or re-establish protected materialold key still works unexpectedlyrotate key and require sign-in

Do not treat biometric failure as an authorization decision. Local authentication can unlock a key; server-side authorization still checks session state, account permissions, action limits, and transaction freshness.

Test evidence and release gate

Owner: mobile security owner records device model, OS version, authenticator policy, and test result. Feature owner records risk decision for fallback. Backend owner records challenge validation. Evidence includes source excerpts, signed build identifier, screen capture of prompt path, and test traces showing no signature or decryption after cancel, lockout, enrollment change, or expired challenge.

Pass when every protected action uses deliberate authenticators, cryptographic binding where key material matters, defined fallback, and server-side replay protection. Fail when a success Boolean alone gates action, fallback is undocumented, protected data remains readable after termination, or changing biometric enrollment leaves sensitive key use intact. Exception: an accessibility or device-support constraint may use device credential only when risk owner documents scope, compensating server controls, expiry, and review date. Remediate by narrowing action, requiring fresh server authentication, rotating keys, then rerunning failure-path tests.

Mobile application penetration testing can inspect the built app and device behavior; it does not replace product approval of transaction risk.

Worked case: beneficiary change

A tester starts an authenticated session, opens a beneficiary-change screen, then invokes the biometric prompt. Capture request bytes before confirmation. Expected output is a one-use server challenge whose signed payload names beneficiary identifier, destination account, operation, expiry, and nonce. Change one destination digit after prompt display and submit original proof. Server should reject it because signed context no longer matches requested change. Repeat after cancellation, biometric lockout, and enrollment modification. Closure evidence is device trace plus server rejection record for each path, keyed only by test run identifier. This test distinguishes prompt presentation from cryptographic authorization.

Edge tests before closure

Attempt to reuse a valid signature, restore app from background, and submit after challenge expiry. Check no pending mutation appears after each rejected request. Test supported device-credential path separately; report its policy decision rather than calling it biometric equivalent. Retest released build, record app version and backend validation version, then close only when failure outputs contain no state change and success output changes exactly requested beneficiary.

Sources

Have a system that needs testing?