AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Biometrics

skill-piyushverma0-android-agent-skills-biometrics · by piyushverma0

|

No reviews yet
0 installs
23 views
0.0% view→install

Install

$ agentstack add skill-piyushverma0-android-agent-skills-biometrics

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-piyushverma0-android-agent-skills-biometrics)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Biometrics? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Biometric Authentication

Rule 1: Check availability before showing biometric UI

// ✅ Check what's available before prompting
fun BiometricManager.canAuthenticateWithBiometrics(): Boolean {
    val authenticators = BIOMETRIC_STRONG or DEVICE_CREDENTIAL
    return canAuthenticate(authenticators) == BiometricManager.BIOMETRIC_SUCCESS
}

// ✅ Detailed availability check
sealed interface BiometricAvailability {
    data object Available : BiometricAvailability
    data object NoHardware : BiometricAvailability
    data object NotEnrolled : BiometricAvailability
    data object Unavailable : BiometricAvailability
}

fun checkBiometricAvailability(context: Context): BiometricAvailability {
    val manager = BiometricManager.from(context)
    return when (manager.canAuthenticate(BIOMETRIC_STRONG or DEVICE_CREDENTIAL)) {
        BiometricManager.BIOMETRIC_SUCCESS -> BiometricAvailability.Available
        BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE,
        BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> BiometricAvailability.NoHardware
        BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> BiometricAvailability.NotEnrolled
        else -> BiometricAvailability.Unavailable
    }
}

Rule 2: BiometricPrompt — correct setup in ComponentActivity

// ✅ Must be created in Activity, not in Composable
class MainActivity : ComponentActivity() {
    private lateinit var biometricPrompt: BiometricPrompt
    private lateinit var promptInfo: BiometricPrompt.PromptInfo

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setupBiometrics()
        setContent { MyApp(onAuthenticateClick = ::showBiometricPrompt) }
    }

    private fun setupBiometrics() {
        val executor = ContextCompat.getMainExecutor(this)
        biometricPrompt = BiometricPrompt(this, executor, object : BiometricPrompt.AuthenticationCallback() {
            override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
                // Handle success — result.cryptoObject available if using CryptoObject
                viewModel.onBiometricSuccess()
            }
            override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
                if (errorCode != BiometricPrompt.ERROR_USER_CANCELED &&
                    errorCode != BiometricPrompt.ERROR_NEGATIVE_BUTTON) {
                    viewModel.onBiometricError(errString.toString())
                }
            }
            override fun onAuthenticationFailed() {
                // Biometric recognized but not matched — DO NOT lock out here
                // BiometricPrompt handles lockout automatically
            }
        })

        promptInfo = BiometricPrompt.PromptInfo.Builder()
            .setTitle("Authenticate")
            .setSubtitle("Use your biometric to unlock the app")
            .setAllowedAuthenticators(BIOMETRIC_STRONG or DEVICE_CREDENTIAL)
            // Don't set setNegativeButtonText when DEVICE_CREDENTIAL is allowed
            .build()
    }

    fun showBiometricPrompt() {
        biometricPrompt.authenticate(promptInfo)
    }
}

Rule 3: Crypto-backed biometrics for secure key operations

// ✅ Biometric-protected Keystore key
object BiometricCryptoHelper {
    private const val KEY_NAME = "biometric_key"

    fun generateKey() {
        val keyGen = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
        keyGen.init(
            KeyGenParameterSpec.Builder(KEY_NAME,
                KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
                .setUserAuthenticationRequired(true)
                .setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG)
                .setInvalidatedByBiometricEnrollment(true)
                .build()
        )
        keyGen.generateKey()
    }

    fun getCipher(): Cipher {
        val key = KeyStore.getInstance("AndroidKeyStore").run {
            load(null)
            getKey(KEY_NAME, null) as SecretKey
        }
        return Cipher.getInstance("${KeyProperties.KEY_ALGORITHM_AES}/${KeyProperties.BLOCK_MODE_CBC}/${KeyProperties.ENCRYPTION_PADDING_PKCS7}").apply {
            init(Cipher.ENCRYPT_MODE, key)
        }
    }
}

// Authenticate with CryptoObject for maximum security
fun showSecureBiometricPrompt() {
    val cipher = BiometricCryptoHelper.getCipher()
    biometricPrompt.authenticate(promptInfo, BiometricPrompt.CryptoObject(cipher))
}

Common Mistakes

❌ Creating BiometricPrompt in Composable — create in Activity, pass lambda to Compose ❌ Setting setNegativeButtonText when DEVICE_CREDENTIAL is allowed — crash ❌ Not checking availability before showing prompt — shows broken UI on unsupported devices ❌ Locking user out on onAuthenticationFailed — BiometricPrompt handles lockout ❌ Using BIOMETRIC_WEAK for sensitive operations — use BIOMETRIC_STRONG with CryptoObject

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.