Part 7: Identity Check - Biometric Hardening & User Intent

  Closing the "Shoulder-Surfing" loophole by enforcing Class 3 biometrics and Keystore invalidation in modern Android architecture.

Identity Check - Biometric Hardening & User Intent

In Part 6, we mastered the networking lifecycle to ensure our sessions are resilient. But there is a final, physical threat that keeps security architects awake at night: The “Shoulder-Surfing” or Stolen Phone Scenario.

If an attacker learns a user’s PIN and then snatches the device while it’s unlocked, they have full user-level control of the device. In this state, a standard “is device guarded” check is no longer enough for high-stakes operations. Today, we implement the final frontier of mobile defense: The Identity Check Pattern.

The Mental Model: Session Authentication $\neq$ Intent Authentication. Being “logged in” is not the same as “authorizing this specific ₹5,00,000 transfer.”

⚡ TL;DR

  • The Problem: An unlocked device is a compromised device once the PIN is leaked — a common real-world fraud vector in fintech.
  • The Solution: Enforcing Strong Biometric-only re-authentication for high-value actions, explicitly disabling PIN fallback.
  • Android Biometric Security: Using BIOMETRIC_STRONG ensures we only accept Class 3 sensors (e.g., 3D Face, secure Fingerprint).
  • The Philosophy: Authenticate the Intent for the specific transaction, not just the device session.

🛑 The Problem: The “Unlocked Device” Fallacy

Traditional mobile security often assumes that if a device is currently unlocked, the person holding it is the authorized owner. However, if an attacker knows the device PIN, they can:

  1. Enroll New Biometrics: On many devices, if an attacker knows the PIN, they may be able to enroll a new biometric, depending on OEM policies.
  2. Bypass Weak Checks: Access sensitive apps that allow a PIN/Pattern fallback when a biometric scan fails or is bypassed.

Standard BiometricPrompt implementations often allow a "Device Credential" (PIN/Pattern) fallback. For a banking or crypto app, this fallback becomes a critical vulnerability once the PIN is compromised. Following BiometricPrompt best practices means closing this loop.

  • User Action → High-Risk Trigger
  • Force BIOMETRIC_STRONG * Success → Execute Action
  • Failure → Block + Trigger MFA / 24-hour Hold

🏛️ The Identity Check Pattern

A Staff-level architect enforces Identity Check for “High-Risk” state changes. This pattern requires the user to prove their identity specifically via a Class 3 (Strong) biometric immediately before the action, even if the phone was already unlocked.

💡 Example: Banking App Scenario

  1. User opens the app; they are already logged in from a previous session.
  2. User attempts a high-value transfer of ₹5,00,000.
  3. Identity Check is triggered: A biometric prompt appears.
  4. The “Use PIN” fallback is disabled. Only a successful fingerprint/face scan allows the transaction to proceed.

🛠️ Implementation: Enforcing “Strong” Re-authentication

In a robust Android app security architecture, we must explicitly exclude DEVICE_CREDENTIAL (PIN/Pattern) and require BIOMETRIC_STRONG.

// 1. Check for Class 3 (Strong) Biometrics only
// BIOMETRIC_STRONG ensures Class 3 auth (e.g., fingerprint, 3D face)
val biometricManager = BiometricManager.from(context)
val authenticators = BiometricManager.Authenticators.BIOMETRIC_STRONG

when (biometricManager.canAuthenticate(authenticators)) {
BiometricManager.BIOMETRIC_SUCCESS -> {
// Device supports and has enrolled strong biometrics
}
BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> {
// High-Risk Fallback: Trigger an Out-of-Band check (e.g., Email MFA)
}
else -> handleIncompatibility()
}

🔍 Deep Dive: Detecting Biometric Tampering

If an attacker knows the PIN and enrolls a new fingerprint, how do we stop them?

Staff-Level Defense: Key Invalidation.

When you generate your signing or encryption keys in the Android Keystore (see Part 2), use:

.setInvalidatedByBiometricEnrollment(true)

If a new biometric is added to the system, the hardware permanently deletes your sensitive keys. When your app attempts an “Identity Check,” the key access will fail. This is a definitive signal that the device’s security state has changed.

⚠️ When NOT to Use Identity Check

  • Low-Risk Apps: News, weather, or simple utility apps where the friction outweighs the value.
  • Low-End Devices: Targeting markets where hardware-backed biometrics are rare.
  • High-Frequency Actions: Don’t trigger a face scan every time a user “likes” a post; it will destroy your UX.

🏁 Key Takeaways

  • The most dangerous state in mobile security isn’t a locked device — it’s an unlocked one in the wrong hands.
  • Strong Biometrics only: Explicitly disable PIN fallback for actions like changing bank details or exporting keys.

Security is not a single checkpoint. It is a continuous verification of:

✔ Who the user is

✔ What device they are using

✔ Whether they truly intend the action

Identity Check is not just a feature. It is the final security boundary between a valid session and a dangerous action.

🙋‍♂️ Frequently Asked Questions (FAQs)

What if the user’s phone only supports “Weak” biometrics?

Most fintech apps will treat a “Weak” (Class 2) biometric the same as a PIN and require a secondary factor (MFA) for high-risk actions to maintain security standards.

💬 Join the Discussion

  • Where do you draw the line between “User Convenience” and “Identity Hardening”?
  • Have you implemented setInvalidatedByBiometricEnrollment? What was the UX impact?

📘 Master Your Next Technical Interview

Since Java is the foundation of Android development, mastering DSA is essential. I highly recommend “Mastering Data Structures & Algorithms in Java”. It’s a focused roadmap covering 100+ coding challenges to help you ace your technical rounds.


Comments

Popular posts from this blog

No More _state + state: Simplifying ViewModels with Kotlin 2.3

Why You Should Stop Passing ViewModels Around Your Compose UI Tree 🚫

Is Jetpack Compose Making Your APK Fatter? (And How to Fix It)