On Android, BiometricPrompt is the standard way to authenticate a user with their fingerprint or face, and like its iOS equivalent it is easy to use in a way that only looks secure. The common mistake is treating the success callback as the security boundary: ask for biometric auth, get a success result, and proceed. That callback is a UI gate, not a guarantee, and on a compromised device it can be defeated. The secure pattern binds the biometric check to a key in the Android Keystore, so a secret is only usable after a genuine, hardware-enforced authentication. Here is how BiometricPrompt works and how to use it securely.
Short answer
BiometricPrompt is Android's standard biometric authentication API, and the secure way to use it is not to trust the success callback alone, which is only a UI gate, but to bind the biometric authentication to a cryptographic key in the Android Keystore. Per Android's biometric guidance, you create a Keystore key that requires user authentication and use it through a BiometricPrompt CryptoObject, so the key, and the secret it protects, can only be used after a successful biometric check enforced by hardware. Use a strong biometric class for crypto-backed authentication, and remember biometrics gate local access, not your server, which still authenticates the session.
What you should know
- BiometricPrompt is the standard API: for fingerprint and face authentication.
- A success callback is not security: it is a UI gate that can be bypassed.
- Bind to a Keystore key: use a CryptoObject tied to a key requiring authentication.
- Hardware enforces it: the key is only usable after a genuine biometric match.
- It does not replace server auth: it gates local access, not the backend.
How does BiometricPrompt work?
It presents the system biometric dialog and reports whether authentication succeeded. Your app builds a BiometricPrompt, specifies the allowed authenticators, biometrics and optionally a device-credential fallback, and shows the prompt; the system runs the fingerprint or face check and calls back with success or failure. BiometricPrompt is the modern, unified API that replaced the older fingerprint API, and it gives a consistent experience across devices. The easy path is to act on the success callback directly in your code, which works but leans entirely on trusting that result. As on iOS, how much that protects depends on what you do with the outcome: a bare success boolean is a convenience gate, not a cryptographic guarantee, so the security comes from how you tie the authentication to something real.
What is the trap with a success boolean?
That a result your code checks can be bypassed on a compromised device. The table contrasts the approaches.
| Approach | What protects the secret |
|---|---|
| Show the prompt, trust the success callback | Your code's check; bypassable if the runtime is compromised |
| Bind biometrics to a Keystore key via CryptoObject | The hardware allows the key only after a genuine match |
| No binding, secret available regardless | Nothing; the gate is cosmetic |
If your app shows the prompt and then reads a secret it already holds on success, an attacker who can manipulate the runtime, on a rooted device, for instance, can make the callback report success or skip the check, since the secret was never tied to the authentication. The secure design stores the secret using a Keystore key that requires user authentication, and uses that key through a CryptoObject in the prompt, so the key is only usable after a real biometric match and the hardware enforces it. Then the authentication protects the secret, not a branch in your code that could be patched.
How do you use it securely?
Tie the biometric check to a Keystore key, and keep the server as the authority. Generate a key in the Android Keystore with the property that it requires user authentication, then perform the sensitive operation, decrypting a stored token or releasing a secret, through that key using a BiometricPrompt CryptoObject, so the key only works after a successful biometric authentication enforced by the hardware. Use a strong biometric class for this crypto-backed flow, since weaker biometrics may not gate a Keystore key, and decide whether to allow a device-credential fallback. Treat biometrics as gating local access to something on the device, while your backend still authenticates the session with proper tokens, because a local biometric success means nothing to your server by itself. The principle, identical to iOS, is that the secret should depend on the authentication, not a boolean.
What to watch out for
The first trap is trusting the BiometricPrompt success callback as if it were security, when it is a UI gate; bind sensitive data to a Keystore key instead. The second is treating a local biometric success as backend authentication, when your server still needs its own session and tokens. The third is using a weak biometric class for a crypto-backed flow, which may not properly gate the key. A pre-submission scan such as PTKD.com (https://ptkd.com) reads the compiled APK or AAB against OWASP MASVS and assesses how your app stores secrets and uses the Keystore, which complements reviewing whether your biometric gate actually protects a secret. The key binding you implement in the app.
What to take away
- BiometricPrompt is Android's standard biometric API, but its success callback is a UI gate, not security.
- The secure pattern binds the biometric check to a Keystore key that requires user authentication, used via a CryptoObject, so the hardware allows the key only after a genuine match.
- Use a strong biometric class for crypto-backed authentication, and remember biometrics gate local access, not your server, which still authenticates the session.
- Use a pre-submission scan such as PTKD.com to check how your app stores secrets and uses the Keystore alongside its biometric flow.


