Identify the design before testing
A callback-only design uses the prompt’s success callback to open the app or release a stored credential. A cryptographic design makes a protected key operation depend on authentication. The server then receives a decrypted refresh token or a signature over its challenge. Write down which design applies. A successful callback does not prove that a key was protected, a session was valid, or a transfer was approved.
The platform checks below cover Android 11 and later, API level 30 or higher. Record the OS version, AndroidX Biometric version, device model, and actual key settings. iOS needs its own LocalAuthentication and Keychain tests; these Android settings do not describe Face ID.
Read the prompt and key settings together
For a biometric-only key used once per prompt, check setUserAuthenticationRequired(true), setUserAuthenticationParameters(0, AUTH_BIOMETRIC_STRONG), and the matching prompt policy. Pass the operation through CryptoObject and record whether it completes after success, cancellation, and lockout. A separate account password button must run account authentication, not set the biometric success flag. Android’s biometric guide describes the prompt and cryptographic paths.
For a device PIN, pattern, or password fallback, check whether both the key and prompt allow device credentials. On API 30 and later, the key can use AUTH_BIOMETRIC_STRONG | AUTH_DEVICE_CREDENTIAL; the prompt uses BIOMETRIC_STRONG | DEVICE_CREDENTIAL. Test the exact configuration on each supported OS version. A product that permits device credentials accepts the security of that device’s lock screen for that operation.
A positive timeout in setUserAuthenticationParameters grants a window for key use after authentication. Test once inside that window and once after it expires. A cancelled prompt inside a valid window does not prove the key was unlocked by cancellation. First let the window expire, then repeat. Keep the authentication timestamp, configured timeout, key operation result, and session result.
Test enrollment against the actual key policy
For a biometric-only key requiring authentication on every use, new biometric enrollment invalidates it by default. setInvalidatedByBiometricEnrollment(false) changes that behavior; allowing AUTH_DEVICE_CREDENTIAL is another exception to enrollment invalidation. Removing the secure lock screen invalidates keys requiring user authentication. These are distinct tests under the KeyGenParameterSpec rules.
Create a test key, save its public key or alias, and prove a valid operation first. Add a fingerprint and retry; compare the result with the recorded policy. In a separate run, remove the secure lock screen and retry. If the key is invalid, require the account’s approved recovery steps before binding a replacement. Record the old key’s server status so a lost key cannot leave a second active device binding by accident.
Synthetic signed-challenge example
Test account A binds public key KA. The server issues challenge C1 for account A and the login action, with a 60-second expiry. Phone A signs the full agreed challenge message after authentication. The server checks the signature, account and action binding, expiry, and whether C1 has been used, then consumes it as part of issuing the session.
Submit the accepted signature again: deny replay. Sign a fresh challenge but submit it after 60 seconds: deny expiry. Sign A’s challenge with test account B’s key: deny the wrong key. Change the action from login to transfer: deny the changed message. Finally send only a client field saying biometric_ok=true: issue no session. These are proposed test cases for this synthetic protocol; the app’s real message format and expiry must be recorded before running them.
Test the stored-token path separately
If the key decrypts a refresh token, trace the decryption and the token exchange separately. Test server revocation and any device binding rule. A protected local key does not turn a bearer refresh token into a device-bound credential. After recovering the test token in an approved lab, try its exchange from phone B and compare the result with the server’s stated policy.
Copy encrypted app storage to phone B and attempt the original key operation. Android Keystore key material is non-exportable, but hardware backing depends on the device and key. Check KeyInfo’s security level before calling a key hardware-backed; Android Keystore guidance explains that distinction. A copied file and a reusable decrypted token are different findings.
Keep a result for every boundary
Save the prompt result, key settings, key operation result, sanitized server request, and final session state. Include success, cancellation, lockout, enrollment change, lock-screen removal, and every supported fallback. For signed challenges, add replay, expiry, wrong key, and wrong action results. Fix the failed boundary and rerun the valid baseline before the negative case.
Related reading
Why these checks matter
The prompt, key operation, and server session are three separate checks. Test all three so a local success screen cannot hide a missing server rule.